示例#1
0
        public void ExecuteDuel(MatchmakingEntry match, int maxNumberOfRounds)
        {
            Assert.NotNull(match, nameof(match));
            Assert.NotNull(match.Adversary, "match.Adversary");
            Assert.NotNull(match.AdversaryRequestedDeck, "match.AdversaryRequestedDeck");
            Assert.NotNull(match.Self, "match.Self");
            Assert.NotNull(match.SelfRequestedDeck, "match.SelfRequestedDeck");

            using (NpgsqlConnection connection = database.CreateAndOpenConnection())
                using (NpgsqlTransaction transaction = connection.BeginTransaction())
                {
                    User winner = null;
                    List <InsertBattleLogEntryModel> battleLogEntries = new List <InsertBattleLogEntryModel>();

                    Deck deck1 = deckRepository.GetDeck(match.Self, match.SelfRequestedDeck, transaction);
                    Deck deck2 = deckRepository.GetDeck(match.Adversary, match.AdversaryRequestedDeck, transaction);

                    Assert.That(deck1.Cards.Count > 0, $"deck1 CardCount must be larger than 0.");
                    Assert.That(deck2.Cards.Count > 0, $"deck2 CardCount must be larger than 0.");
                    Assert.That(deck1.Cards.Count == deck2.Cards.Count, $"deck1 CardCount must be equal to deck2 CardCount.");

                    int currentRound;

                    for (currentRound = 0; currentRound < maxNumberOfRounds; currentRound++)
                    {
                        if (deck1.Cards.Count == 0)
                        {
                            winner = deck2.Player;
                            break;
                        }
                        else if (deck2.Cards.Count == 0)
                        {
                            winner = deck1.Player;
                            break;
                        }

                        int cardNumber_Deck1 = randomNumberGenerator.Next() % deck1.Cards.Count;
                        int cardNumber_Deck2 = randomNumberGenerator.Next() % deck2.Cards.Count;

                        Card card1 = deck1.Cards[cardNumber_Deck1];
                        Card card2 = deck2.Cards[cardNumber_Deck2];

                        int effectiveAttackPointsCard1 = GetEffectiveAttackPoints(card1, card2);
                        int effectiveAttackPointsCard2 = GetEffectiveAttackPoints(card2, card1);

                        InsertBattleLogEntryModel logEntry = new InsertBattleLogEntryModel()
                        {
                            Card1 = card1,
                            Card2 = card2,
                            Order = currentRound
                        };

                        StringBuilder roundDescriptionBuilder = new StringBuilder();
                        roundDescriptionBuilder.Append(BuildPlayerCardSummary(deck1.Player, card1, effectiveAttackPointsCard1));
                        roundDescriptionBuilder.Append(" vs. ");
                        roundDescriptionBuilder.AppendLine(BuildPlayerCardSummary(deck2.Player, card2, effectiveAttackPointsCard2));
                        roundDescriptionBuilder.Append("Result: ");

                        if (effectiveAttackPointsCard1 == effectiveAttackPointsCard2)
                        {
                            roundDescriptionBuilder.Append("Tie.");
                        }
                        else if (effectiveAttackPointsCard1 > effectiveAttackPointsCard2)
                        {
                            roundDescriptionBuilder.Append(BuildWinnerSummary(deck1.Player, currentRound));
                            deck1.Cards.Add(card2);
                            deck2.Cards.Remove(card2);
                        }
                        else
                        {
                            roundDescriptionBuilder.Append(BuildWinnerSummary(deck2.Player, currentRound));
                            deck2.Cards.Add(card1);
                            deck1.Cards.Remove(card1);
                        }

                        logEntry.DeckState1       = deck1.GenerateDeckStateString();
                        logEntry.DeckState2       = deck2.GenerateDeckStateString();
                        logEntry.RoundDescription = roundDescriptionBuilder.ToString();

                        battleLogEntries.Add(logEntry);
                    }

                    InsertBattleLogModel battleLog = new InsertBattleLogModel()
                    {
                        Match_ID     = match.MatchID,
                        Winner       = winner,
                        BattleResult = GetBattleResult(winner, deck1.Player, deck2.Player),
                        Deck1        = deck1,
                        Deck2        = deck2,
                        CreationDate = DateTime.Now,
                        Turns        = currentRound
                    };

                    int battleLogID = battleLogRepository.InsertBattleLog(battleLog, transaction);
                    foreach (InsertBattleLogEntryModel logEntryModel in battleLogEntries)
                    {
                        battleLogRepository.InsertBattleLogEntry(battleLogID, logEntryModel, transaction);
                    }

                    transaction.Commit();
                }
        }
        public MatchmakingEntry FindMatch(RequestContext requestContext, string requestedDeck)
        {
            using (NpgsqlConnection connection = database.CreateAndOpenConnection())
                using (NpgsqlTransaction transaction = connection.BeginTransaction())
                {
                    UserSession session = CookieAuthenticationModule.GetUserSessionFromRequest(requestContext, transaction);
                    User        user    = userRepository.GetUser(session.UserID, transaction);
                    Assert.NotNull(user, nameof(user));

                    Validate.Condition(deckRepository.Exists(requestedDeck, user.UserID, transaction), $"Requested Deck: {requestedDeck} could not be found for User: {user.UserName}");

                    MatchmakingEntry self = new MatchmakingEntry(user, requestedDeck);

                    lock (duelQueue)
                    {
                        if (duelQueue.Any(mme => mme.Self.UserID == user.UserID || mme.Adversary?.UserID == user.UserID))
                        {
                            throw new InvalidOperationException(
                                      $"Gegnersuche fehlgeschlagen. Der Benutzer: {user.UserName} " +
                                      "ist dem Matchmaking bereits beigetreten.");
                        }

                        duelQueue.Add(self);
                    }

                    const int maxAttemptCount = 60;

                    int currentAttempt         = 0;
                    MatchmakingEntry adversary = null;

                    do
                    {
                        ++currentAttempt;
                        Thread.Sleep(2000);

                        lock (duelQueue)
                        {
                            if (self.IsMatched)
                            {
                                return(self);
                            }

                            adversary = duelQueue
                                        .FirstOrDefault(mmEntry => mmEntry != self);

                            if (adversary != null)
                            {
                                Guid matchID = Guid.NewGuid();

                                adversary.Adversary = user;
                                adversary.AdversaryRequestedDeck = requestedDeck;
                                adversary.IsMatched = true;
                                adversary.MatchID   = matchID;

                                duelQueue.Remove(adversary);

                                self.Adversary = adversary.Self;
                                self.AdversaryRequestedDeck = adversary.SelfRequestedDeck;
                                self.IsMatched      = true;
                                self.ShouldInitiate = true;
                                self.MatchID        = matchID;
                                duelQueue.Remove(self);

                                return(self);
                            }
                        }
                    } while (currentAttempt <= maxAttemptCount);

                    // no Match could be found -> deregister.
                    lock (duelQueue)
                    {
                        duelQueue.Remove(self);
                    }

                    return(self);
                }
        }