Ejemplo n.º 1
0
        public async Task SetRostersWithNoRolesInChannelSucceeds()
        {
            PlayerTeamPair[] playerTeamPairs = new PlayerTeamPair[]
            {
                new PlayerTeamPair(1, "Alice", FirstTeam),
                new PlayerTeamPair(2, "Alan", FirstTeam),
                new PlayerTeamPair(3, "Bob", SecondTeam)
            };
            IEnumerable <IGrouping <string, PlayerTeamPair> > grouping = playerTeamPairs.GroupBy(pair => pair.TeamId);
            IReadOnlyDictionary <string, string> teamIdToNames         = playerTeamPairs
                                                                         .Select(pair => pair.TeamId)
                                                                         .Distinct()
                                                                         .ToDictionary(key => key);

            Mock <IByRoleTeamManager> mockTeamManager = new Mock <IByRoleTeamManager>();

            mockTeamManager
            .Setup(manager => manager.GetTeamIdToNamesForServer())
            .Returns(Task.FromResult(teamIdToNames));
            mockTeamManager
            .Setup(manager => manager.GetPlayerTeamPairsForServer())
            .Returns(Task.FromResult(grouping));

            mockTeamManager
            .Setup(manager => manager.GetTeamIdToNames())
            .Returns(Task.FromResult <IReadOnlyDictionary <string, string> >(new Dictionary <string, string>()));
            mockTeamManager
            .Setup(manager => manager.GetKnownPlayers())
            .Returns(Task.FromResult(Enumerable.Empty <PlayerTeamPair>()));

            IByRoleTeamManager teamManager = mockTeamManager.Object;

            await ValidateDefaultRostersSet(teamManager);
        }
Ejemplo n.º 2
0
        private async Task ValidateDefaultRostersSet(IByRoleTeamManager teamManager)
        {
            IResult <string> result = await this.Generator.TryUpdateRosters(teamManager, SheetsUri);

            Assert.IsTrue(result.Success, "Update should've succeeded");

            Assert.AreEqual(1, this.ClearedRanges.Count, "Unexpected number of clears");
            Assert.AreEqual($"'{UCSDGoogleSheetsGenerator.RostersSheetName}'!A2:G999", this.ClearedRanges[0], "Unexpected range");

            Assert.AreEqual(2, this.UpdatedRanges.Count, "Unexpected number of update ranges");

            UpdateRange updateRange = this.UpdatedRanges[0];

            Assert.AreEqual(
                $"'{UCSDGoogleSheetsGenerator.RostersSheetName}'!A2:C2",
                updateRange.Range,
                "Unexpected range for the first team");
            CollectionAssert.AreEquivalent(
                new string[] { FirstTeam, "Alice", "Alan" },
                updateRange.Values.ToArray(),
                "Unexpected row for the first team");

            updateRange = this.UpdatedRanges[1];
            Assert.AreEqual(
                $"'{UCSDGoogleSheetsGenerator.RostersSheetName}'!A3:B3",
                updateRange.Range,
                "Unexpected range for the second team");
            CollectionAssert.AreEquivalent(
                new string[] { SecondTeam, "Bob" },
                updateRange.Values.ToArray(),
                "Unexpected row for the second team");
        }
Ejemplo n.º 3
0
        public async Task TryCreateScoresheetPastPhaseLimitFails()
        {
            IByRoleTeamManager teamManager = CreateDefaultTeamManager();
            GameState          game        = new GameState()
            {
                Format      = Format.CreateTossupShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            for (int i = 0; i < this.Generator.PhasesLimit; i++)
            {
                await game.AddPlayer(2, "Alice");

                game.ScorePlayer(10);
            }

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Creation should've succeeded at the limit.");

            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(15);

            result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Creation should've succeeded.");
            this.AssertInUpdateRange($"'Round 1'!C27", "10", "Couldn't find the last buzz");
            Assert.IsFalse(
                this.UpdatedRanges
                .Any(valueRange => valueRange.Values.Any(v => v.ToString() == "15")),
                "Last buzz should've been cut off, but we found a power");
        }
Ejemplo n.º 4
0
        public async Task TryCreateScoresheetAtPhasesLimitSucceeds()
        {
            IByRoleTeamManager teamManager = CreateDefaultTeamManager();

            GameState game = new GameState()
            {
                Format      = Format.CreateTossupBonusesShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            for (int i = 0; i < this.Generator.PhasesLimit - 1; i++)
            {
                await game.AddPlayer(2, "Alice");

                game.ScorePlayer(10);
                Assert.IsTrue(game.TryScoreBonus("0"), $"Scoring a bonus should've succeeded in phase {i}");
            }

            await game.AddPlayer(4, "Bob");

            game.ScorePlayer(-5);
            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(15);

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Creation should've succeeded at the limit.");

            int lastRow = this.Generator.FirstPhaseRow + this.Generator.PhasesLimit - 1;

            this.AssertInUpdateRange($"'Round 1'!C{lastRow}", "15", "Couldn't find Alice's buzz");
            this.AssertInUpdateRange($"'Round 1'!O{lastRow}", "-5", "Couldn't find Bob's buzz");
        }
Ejemplo n.º 5
0
        public async Task TryCreateScoresheetOneTeamAndIndividual()
        {
            const string firstTeamPlayer = "Alice";
            const string individualName  = "Individual";

            IByRoleTeamManager teamManager = CreateTeamManager(new PlayerTeamPair(2, firstTeamPlayer, FirstTeam));

            GameState game = new GameState()
            {
                Format      = Format.CreateTossupShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            await game.AddPlayer(2, firstTeamPlayer);

            game.ScorePlayer(10);
            await game.AddPlayer(3, individualName);

            game.ScorePlayer(15);

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Creation should've succeeded");

            // n^2 runtime, but not that many checks or update ranges, so it should be okay

            this.AssertInUpdateRange($"'Round 1'!C1", FirstTeam, "Couldn't find the first team's name");
            this.AssertInUpdateRange($"'Round 1'!O1", individualName, "Couldn't find the second team's name");
            this.AssertInUpdateRange($"'Round 1'!C3", firstTeamPlayer, "Couldn't find the first team's player name");
            this.AssertInUpdateRange($"'Round 1'!O3", individualName, "Couldn't find the indivual team's player name");
            this.AssertInUpdateRange($"'Round 1'!C4", "10", "Couldn't find the buzz from the first team");
            this.AssertInUpdateRange($"'Round 1'!O5", "15", "Couldn't find the buzz from the individual team");
        }
Ejemplo n.º 6
0
        public async Task SetRostersFailsWithTooManyPlayers()
        {
            List <PlayerTeamPair> players = new List <PlayerTeamPair>();

            for (int i = 0; i < this.Generator.PlayersPerTeamLimit; i++)
            {
                players.Add(new PlayerTeamPair((ulong)i, $"{i}", FirstTeam));
            }

            IByRoleTeamManager teamManager = CreateTeamManager(players.ToArray());

            IResult <string> result = await this.Generator.TryUpdateRosters(teamManager, SheetsUri);

            Assert.IsTrue(result.Success, $"Update should've succeeded at the limit.");

            players.Add(new PlayerTeamPair(1111, "OverLimit", FirstTeam));
            teamManager = CreateTeamManager(players.ToArray());

            result = await this.Generator.TryUpdateRosters(teamManager, SheetsUri);

            Assert.IsFalse(result.Success, $"Update should've failed after the limit.");
            Assert.AreEqual(
                $"Couldn't write to the sheet. Rosters can only support up to {this.Generator.PlayersPerTeamLimit} players per team.",
                result.ErrorMessage,
                "Unexpected error message");
        }
Ejemplo n.º 7
0
        public async Task TryCreateScoresheetWithMoreThanTwoTeamsFails()
        {
            PlayerTeamPair[] players = new PlayerTeamPair[3];
            for (int i = 0; i < players.Length; i++)
            {
                players[i] = new PlayerTeamPair((ulong)i + 100, $"Player{i}", $"Team{i}");
            }

            IByRoleTeamManager teamManager = CreateTeamManager(players);

            GameState game = new GameState()
            {
                Format      = Format.CreateTossupBonusesShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(10);

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsFalse(result.Success, $"Creation succeeded when it should've failed.");
            Assert.AreEqual(
                "Couldn't write to the sheet. Export only works if there are 1 or 2 teams in the game.",
                result.ErrorMessage,
                "Unexpected error message");
        }
Ejemplo n.º 8
0
        public async Task TryCreateScoresheetWithDeadTossups()
        {
            IByRoleTeamManager teamManager = CreateDefaultTeamManager();

            // Do something simple, then read the spreadsheet and verify some fields
            GameState game = new GameState()
            {
                Format      = Format.CreateTossupBonusesShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(-5);
            game.NextQuestion();
            game.NextQuestion();

            await game.AddPlayer(4, "Bob");

            game.ScorePlayer(10);
            game.TryScoreBonus("0/10/0");

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Failed: {(result.Success ? "" : result.ErrorMessage)}");

            // These checks are O(n^2), since we do Any for all of them. However, n is small here (~15), so it's not
            // too bad.

            // Tossups
            this.AssertInUpdateRange("'ROUND 1'!C4", "-5", "Couldn't find Alice's buzz");
            this.AssertInUpdateRange("'ROUND 1'!I4", "DT", "Couldn't find the first dead tossup marker");
            this.AssertInUpdateRange("'ROUND 1'!I5", "DT", "Couldn't find the second dead tossup marker");

            // Bonuses
            UpdateRange updateRange = this.UpdatedRanges
                                      .FirstOrDefault(valueRange => valueRange.Range == "'ROUND 1'!S6");

            Assert.IsNotNull(updateRange, "Couldn't find range for the bonus");
            CollectionAssert.AreEquivalent(
                new int[] { 10 },
                updateRange.Values.ToArray(),
                "Unexpected scoring for the bonus");
        }
Ejemplo n.º 9
0
        public async Task NoBonusesWrittenAfterBonusLimit()
        {
            IByRoleTeamManager teamManager = CreateDefaultTeamManager();

            GameState game = new GameState()
            {
                Format      = Format.CreateTossupBonusesShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            int lastBonusPhase = this.Generator.LastBonusRow - this.Generator.FirstPhaseRow;

            for (int i = 0; i < lastBonusPhase; i++)
            {
                await game.AddPlayer(2, "Alice");

                game.ScorePlayer(10);
                Assert.IsTrue(game.TryScoreBonus("0"), $"Scoring a bonus should've succeeded in phase {i}");
            }

            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(15);
            Assert.IsTrue(game.TryScoreBonus("30"), $"Scoring a bonus should've succeeded in the last phase");

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Creation should've succeeded at the limit.");

            UpdateRange updateRange = this.UpdatedRanges
                                      .FirstOrDefault(valueRange => valueRange.Range == $"'Round 1'!I{this.Generator.LastBonusRow}:K{this.Generator.LastBonusRow}");

            Assert.IsNotNull(updateRange, "Couldn't find range for the last bonus");
            CollectionAssert.AreEquivalent(
                new bool[] { true, true, true },
                updateRange.Values.ToArray(),
                "Unexpected scoring for the last bonus");

            updateRange = this.UpdatedRanges
                          .FirstOrDefault(valueRange => valueRange.Range == $"'Round 1'!I{this.Generator.LastBonusRow + 1}:K{this.Generator.LastBonusRow + 1}");
            Assert.IsNull(updateRange, "Bonus past the last bonus phase should'nt be exported");
        }
Ejemplo n.º 10
0
        public async Task TryCreateScoresheetWithDeadTossupsInTiebreakers()
        {
            IByRoleTeamManager teamManager = CreateDefaultTeamManager();

            // Do something simple, then read the spreadsheet and verify some fields
            GameState game = new GameState()
            {
                Format      = Format.CreateTossupBonusesShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            for (int i = 0; i < this.Generator.PhasesLimit - 1; i++)
            {
                game.NextQuestion();
            }

            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(15);

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Failed: {(result.Success ? "" : result.ErrorMessage)}");

            // These checks are O(n^2), since we do Any for all of them. However, n is small here (~15), so it's not
            // too bad.

            // Tossups
            // FirstRowPhase is included in the limit, so subtract 1 from what the row should be
            int buzzRow = this.Generator.PhasesLimit + this.Generator.FirstPhaseRow - 1;

            this.AssertInUpdateRange($"'ROUND 1'!C{buzzRow}", "15", "Couldn't find Alice's buzz");
            this.AssertInUpdateRange("'ROUND 1'!I4", "DT", "Couldn't find the first dead tossup marker");
            this.AssertInUpdateRange($"'ROUND 1'!I{this.Generator.LastBonusRow + 1}", "DT", "Couldn't find the tiebreaker dead tossup marker");

            // No bonus in the tie breaker
            UpdateRange updateRange = this.UpdatedRanges
                                      .FirstOrDefault(valueRange => valueRange.Range == $"'ROUND 1'!I{buzzRow}");

            Assert.IsNull(updateRange, "There shouldn't be an update for the bonus yet");
        }
Ejemplo n.º 11
0
        public async Task TryCreateScoresheetPastPlayerLimitFails()
        {
            List <PlayerTeamPair> players = new List <PlayerTeamPair>();

            for (int i = 0; i < this.Generator.PlayersPerTeamLimit; i++)
            {
                players.Add(new PlayerTeamPair((ulong)i + 2, $"Player{i}", FirstTeam));
                players.Add(new PlayerTeamPair((ulong)i + 200, $"Player{i}", SecondTeam));
            }

            IByRoleTeamManager teamManager = CreateTeamManager(players.ToArray());

            GameState game = new GameState()
            {
                Format      = Format.CreateTossupShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Creation should've succeeded at the limit.");

            players.Add(new PlayerTeamPair(1111, "OverLimit", FirstTeam));
            teamManager      = CreateTeamManager(players.ToArray());
            game.TeamManager = teamManager;

            // We need to force an update to the game, so we don't have cached stats
            await game.AddPlayer(2, "Player2");

            game.ScorePlayer(0);

            result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsFalse(result.Success, $"Creation should've failed after the limit.");
            Assert.AreEqual(
                $"Couldn't write to the sheet. Export only currently works if there are at most {this.Generator.PlayersPerTeamLimit} players on a team.",
                result.ErrorMessage,
                "Unexpected error message");
        }
Ejemplo n.º 12
0
        public async Task TryCreateScoresheetWithoutTeamsFails()
        {
            IByRoleTeamManager teamManager = CreateTeamManager();

            GameState game = new GameState()
            {
                Format      = Format.CreateTossupBonusesShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(10);

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsFalse(result.Success, $"Creation succeeded when it should've failed.");
            Assert.AreEqual(
                "Couldn't write to the sheet. Export only works if there are 1 or 2 teams in the game.",
                result.ErrorMessage,
                "Unexpected error message");
        }
Ejemplo n.º 13
0
        public async Task <IResult <string> > TryUpdateRosters(IByRoleTeamManager teamManager, Uri sheetsUri)
        {
            Verify.IsNotNull(teamManager, nameof(teamManager));
            Verify.IsNotNull(sheetsUri, nameof(sheetsUri));

            IEnumerable <IGrouping <string, PlayerTeamPair> > groupings = await teamManager.GetPlayerTeamPairsForServer();

            if (groupings.Any(grouping => grouping.Count() > this.PlayersPerTeamLimit))
            {
                return(CreateFailureResult(
                           $"Rosters can only support up to {this.PlayersPerTeamLimit} players per team."));
            }

            int groupingsCount = groupings.Count();

            if (groupingsCount == 0)
            {
                return(CreateFailureResult($"No teams were found, so the rosters remain unchanged."));
            }
            else if (groupingsCount > this.TeamsLimit)
            {
                return(CreateFailureResult(
                           $"Rosters can only support up to {this.TeamsLimit} teams."));
            }

            IReadOnlyDictionary <string, string> teamIdToNames = await teamManager.GetTeamIdToNamesForServer();

            IResult <List <ValueRange> > rangesResult = this.GetUpdateRangesForRoster(teamIdToNames, groupings);

            if (!rangesResult.Success)
            {
                return(CreateFailureResult(rangesResult.ErrorMessage));
            }

            return(await this.SheetsApi.UpdateGoogleSheet(rangesResult.Value, this.ClearRostersRanges, sheetsUri));
        }
Ejemplo n.º 14
0
        public async Task TryCreateScoresheetSucceeds()
        {
            // Do something simple, then read the spreadsheet and verify some fields
            IByRoleTeamManager teamManager = CreateDefaultTeamManager();

            // Do something simple, then read the spreadsheet and verify some fields
            GameState game = new GameState()
            {
                Format      = Format.CreateTossupBonusesShootout(false),
                ReaderId    = 1,
                TeamManager = teamManager
            };

            await game.AddPlayer(2, "Alice");

            game.ScorePlayer(15);
            game.TryScoreBonus("10/0/10");

            await game.AddPlayer(3, "Alan");

            game.ScorePlayer(-5);
            await game.AddPlayer(4, "Bob");

            game.ScorePlayer(10);
            game.TryScoreBonus("0/10/0");

            IResult <string> result = await this.Generator.TryCreateScoresheet(game, SheetsUri, 1);

            Assert.IsTrue(result.Success, $"Failed: {(result.Success ? "" : result.ErrorMessage)}");

            // Assert we cleared these two fields
            Assert.IsTrue(this.ClearedRanges.Contains("'Round 1'!C4:H31"), "First team scores are not in the list of cleared ranges");
            Assert.IsTrue(this.ClearedRanges.Contains("'Round 1'!O4:T31"), "Second team scores are not in the list of cleared ranges");

            // Assert we cleared the second team and the players
            Assert.IsTrue(this.ClearedRanges.Contains("'Round 1'!O1:O1"), "Second team name wasn't cleared");
            Assert.IsTrue(this.ClearedRanges.Contains("'Round 1'!C3:H3"), "First team's player names weren't cleared");
            Assert.IsTrue(this.ClearedRanges.Contains("'Round 1'!O3:T3"), "Second team's player names weren't cleared");

            // These checks are O(n^2), since we do Any for all of them. However, n is small here (~15), so it's not
            // too bad.

            // Team names
            this.AssertInUpdateRange("'Round 1'!C1", FirstTeam, "Couldn't find first team");
            this.AssertInUpdateRange("'Round 1'!O1", SecondTeam, "Couldn't find second team");

            // Player names
            this.AssertInUpdateRange("'Round 1'!C3", "Alice", "Couldn't find Alice");
            this.AssertInUpdateRange("'Round 1'!D3", "Alan", "Couldn't find Alan");
            this.AssertInUpdateRange("'Round 1'!O3", "Bob", "Couldn't find Bob");

            // Tossups
            this.AssertInUpdateRange("'Round 1'!C4", "15", "Couldn't find Alice's buzz");
            this.AssertInUpdateRange("'Round 1'!D5", "-5", "Couldn't find Alan's buzz");
            this.AssertInUpdateRange("'Round 1'!O5", "10", "Couldn't find Bob's buzz");

            // Bonuses
            UpdateRange updateRange = this.UpdatedRanges
                                      .FirstOrDefault(valueRange => valueRange.Range == "'Round 1'!I4:K4");

            Assert.IsNotNull(updateRange, "Couldn't find range for the first bonus");
            CollectionAssert.AreEquivalent(
                new bool[] { true, false, true },
                updateRange.Values.ToArray(),
                "Unexpected scoring for the first bonus");

            updateRange = this.UpdatedRanges
                          .FirstOrDefault(valueRange => valueRange.Range == "'Round 1'!U5:W5");
            Assert.IsNotNull(updateRange, "Couldn't find range for the second bonus");
            CollectionAssert.AreEquivalent(
                new bool[] { false, true, false },
                updateRange.Values.ToArray(),
                "Unexpected scoring for the second bonus");
        }
Ejemplo n.º 15
0
        public async Task SetRostersSucceeds()
        {
            IByRoleTeamManager teamManager = CreateDefaultTeamManager();

            await ValidateDefaultRostersSet(teamManager);
        }