private void UpdateTeamPoints(AiPortalDbContext data, Team team) { if (!data.Battles.Where(x => x.FirstTeamId == team.Id || x.SecondTeamId == team.Id).All(x => x.IsFinished)) { // Update player points only when all battles are finished return; } var teamHasUploadedFile = team.Uploads.Any(); var battles = data.Battles.Where(x => x.FirstTeamId == team.Id || x.SecondTeamId == team.Id) .Select( x => new { TeamIsFirst = x.FirstTeamId == team.Id, OpponentHasUploadedFile = x.FirstTeamId == team.Id ? x.SecondTeam.Uploads.Any() : x.FirstTeam.Uploads.Any(), BattlesWonByTeam = x.BattleGameResults.Count( res => res.BattleGameWinner == (x.FirstTeamId == team.Id ? BattleGameWinner.First : BattleGameWinner.Second)), }); var points = 0; foreach (var battle in battles) { if (teamHasUploadedFile && battle.OpponentHasUploadedFile) { // Both players have submitted file, so the result from battles will be used points += battle.BattlesWonByTeam; } else if (teamHasUploadedFile && !battle.OpponentHasUploadedFile) { // The other player does not have uploaded file and current player has points += 0; } else if (!teamHasUploadedFile && battle.OpponentHasUploadedFile) { // The other player has uploaded file and current player hasn't points += 0; } else if (!teamHasUploadedFile && !battle.OpponentHasUploadedFile) { // Both players hasn't uploaded file points += 0; } } // TODO: What about multithreading? // TODO: Depend on max games when scoring team.Points = points; this.logger.InfoFormat("Points for {0} updated.", team.Name); data.SaveChanges(); }
public void Start() { this.logger.Info("BattlesSimulatorJob starting..."); while (!this.stopping) { var data = new AiPortalDbContext(); Battle battle; try { battle = data.Battles.Where(x => !x.IsFinished) .OrderBy(x => x.FirstTeam.CompetitionId) // Temporary, remove it. .ThenBy(x => Guid.NewGuid()) .FirstOrDefault(); } catch (Exception exception) { this.logger.FatalFormat("Unable to get battle for processing. Exception: {0}", exception); throw; } if (battle == null) { // No battle available. Wait 10 seconds and try again. Thread.Sleep(10000); continue; } if (!this.processingBattleIds.Add(battle.Id)) { // Other thread is processing the same battle. Wait 1 second and choose another battle for simulating. Thread.Sleep(1000); continue; } try { foreach (var battleGameResult in battle.BattleGameResults.ToList()) { data.BattleGameResults.Remove(battleGameResult); } this.ProcessBattle(data, battle); battle.IsFinished = true; } catch (Exception exception) { this.logger.ErrorFormat("ProcessBattle on battle №{0} has thrown an exception: {1}", battle.Id, exception); battle.Comment = $"Exception in ProcessBattle: {exception.Message}"; } try { data.SaveChanges(); } catch (Exception exception) { this.logger.ErrorFormat("Unable to save changes to the battle №{0}! Exception: {1}", battle.Id, exception); } try { this.UpdateTeamPoints(data, battle.FirstTeam); this.UpdateTeamPoints(data, battle.SecondTeam); } catch (Exception exception) { this.logger.ErrorFormat("Unable to update team points! Exception: {0}", exception); } // Next line removes the battle from the list. Fixes problem with retesting battles. this.processingBattleIds.Remove(battle.Id); } this.logger.Info("BattlesSimulatorJob stopped."); }
private void ProcessBattle(AiPortalDbContext data, Battle battle) { this.logger.InfoFormat("Processing battle №{0} started.", battle.Id); var firstUpload = battle.FirstTeam.Uploads.OrderByDescending(x => x.Id).FirstOrDefault(); var secondUpload = battle.SecondTeam.Uploads.OrderByDescending(x => x.Id).FirstOrDefault(); if (firstUpload == null && secondUpload == null) { battle.Comment = "Both teams didn't upload any file."; } else if (firstUpload == null) { battle.Comment = $"Team {battle.FirstTeam.Name} didn't upload any file."; } else if (secondUpload == null) { battle.Comment = $"Team {battle.SecondTeam.Name} didn't upload any file."; } else { var simulationResult = this.gamesSimulator.SimulateGames( firstUpload.FileContents, secondUpload.FileContents, battle.FirstTeam.Competition.GamesExecutorClassName); foreach (var gameResult in simulationResult.GameResults) { var battleGameResult = new BattleGameResult { BattleId = battle.Id, BattleGameWinner = gameResult.Winner, Report = gameResult.Report, }; battle.BattleGameResults.Add(battleGameResult); } battle.Comment = simulationResult.BattleComment; } this.logger.InfoFormat("Processing battle №{0} ended.", battle.Id); }