Exemplo n.º 1
0
        public async Task ShowLeaderboard(LeaderboardType type = LeaderboardType.Global)
        {
            if (type == LeaderboardType.Global)
            {
                var top = _leaderboard.GetTopRank(15);
                await ReplyAsync(embed : await FormatLeaderboard(top));
            }
            else if (type == LeaderboardType.Current)
            {
                var challenge = await _challenges.GetCurrentChallenge();

                if (challenge == null)
                {
                    await ReplyAsync("There is no currently running challenge");

                    return;
                }

                await DisplayChallengeLeaderboard(challenge);
            }
            else
            {
                throw new InvalidOperationException("Unknown leaderboard type");
            }
        }
Exemplo n.º 2
0
        public async Task SubmitSolution([Remainder] string input)
        {
            var challenge = await _challenges.GetCurrentChallenge();

            if (challenge == null)
            {
                await ReplyAsync("There is no currently running challenge!");

                return;
            }

            await SubmitSolution(challenge, input, true);
        }
Exemplo n.º 3
0
        public async Task SetDifficulty(ChallengeDifficulty difficulty)
        {
            var current = await _challenges.GetCurrentChallenge();

            if (current == null)
            {
                await ReplyAsync("There is no current challenge");
            }
            else
            {
                await _challenges.ChangeChallengeDifficulty(current, difficulty);
                await ReplyAsync($"Changed difficulty from `{current.Difficulty}` to `{difficulty}`");
            }
        }
Exemplo n.º 4
0
        public async Task ShowLeaderboard(LeaderboardType type = LeaderboardType.Global)
        {
            if (type == LeaderboardType.Global)
            {
                var top = _leaderboard.GetTopRank(15);
                await ReplyAsync(embed : await FormatLeaderboard(top));
            }
            else if (type == LeaderboardType.Current)
            {
                var challenge = await _challenges.GetCurrentChallenge();

                if (challenge == null)
                {
                    await ReplyAsync("There is no currently running challenge");

                    return;
                }

                // Get the top N solutions
                var top5 = _solutions.GetSolutions(challenge.Id, 20).Select(a => new RankInfo(a.Solution.UserId, a.Rank, a.Solution.Score));

                // Get your own rank
                var self = await _solutions.GetRank(challenge.Id, Context.User.Id);

                RankInfo?selfRank = null;
                if (self.HasValue)
                {
                    selfRank = new RankInfo(self.Value.Solution.UserId, self.Value.Rank, self.Value.Solution.Score);
                }

                await ReplyAsync(embed : await FormatLeaderboard(top5, selfRank));
            }
            else
            {
                throw new InvalidOperationException("Unknown leaderboard type");
            }
        }
Exemplo n.º 5
0
        public async Task CurrentCompetition()
        {
            var current = await _challenges.GetCurrentChallenge();

            if (current == null)
            {
                await ReplyAsync("There is no challenge currently running");
            }
            else
            {
                var message = await ReplyAsync(embed : current.ToEmbed().Build());

                _cron.Schedule(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(1), uint.MaxValue, async() => {
                    // Get current challenge
                    var c = await _challenges.GetCurrentChallenge();

                    // Update embed
                    await message.ModifyAsync(a => a.Embed = current.ToEmbed().Build());

                    // Keep running this task while the challenge is the same challenge that was initially scheduled
                    return(c?.Id == current.Id);
                });
            }
        }
Exemplo n.º 6
0
        public async Task CurrentCompetition()
        {
            var current = await _challenges.GetCurrentChallenge();

            if (current == null)
            {
                await ReplyAsync("There is no challenge currently running");
            }
            else
            {
                var message = await ReplyAsync(embed : current.ToEmbed().Build());

                await _messages.TrackMessage(message.Channel.Id, message.Id, current.Id, MessageType.Current);
            }
        }
Exemplo n.º 7
0
        public async Task UpdateCurrentMessage(Message message)
        {
            var currentChallenge = await _challenges.GetCurrentChallenge();

            var challenge = await _challenges.GetChallenges(id : message.ChallengeID).FirstAsync();

            if (challenge == null)
            {
                Console.WriteLine("Message exists for inexistant challenge " + message.ChallengeID);
                await RemoveMessage(message);
            }
            else
            {
                if (!(_client.GetChannel(message.ChannelID) is ISocketMessageChannel channel))
                {
                    Console.WriteLine($"No such channel: {message.ChannelID}");
                    await RemoveMessage(message);

                    return;
                }

                if (!((await channel.GetMessageAsync(message.MessageID)) is IUserMessage msg))
                {
                    Console.WriteLine($"No such message: {message.MessageID}");
                    await RemoveMessage(message);

                    return;
                }

                await msg.ModifyAsync(a => a.Embed = challenge.ToEmbed().Build());

                if (currentChallenge == null || challenge.Id != currentChallenge.Id)
                {
                    await RemoveMessage(message);
                }
            }
        }
Exemplo n.º 8
0
        public async Task Start()
        {
            while (true)
            {
                State = SchedulerState.StartingChallenge;

                // Find the currently running challenge
                var current = await _challenges.GetCurrentChallenge();

                // If there is no challenge running try to start a new one
                if (current == null)
                {
                    Console.WriteLine("There is no current challenge - attempting to start a new one");

                    // Start the next challenge, if there isn't one wait a while
                    var next = await _challenges.StartNext();

                    if (next == null)
                    {
                        Console.WriteLine("No challenges available, waiting for a while...");
                        State = SchedulerState.WaitingNoChallengesInPool;
                        await Task.Delay(TimeSpan.FromMinutes(1));

                        continue;
                    }

                    Console.WriteLine($"Starting new challenge {next.Name}");

                    // Notify all subscribed channels about the new challenge
                    await NotifyStart(next);

                    current = next;
                }
                else
                {
                    Console.WriteLine($"{current.Name} challenge is currently running");
                }

                //There is a challenge running, wait until the end time or until someone externally pokes us awake
                var endTime = current.EndTime;
                while (endTime != null && endTime > DateTime.UtcNow)
                {
                    var delay = endTime.Value - DateTime.UtcNow;
                    if (delay > TimeSpan.Zero)
                    {
                        State = SchedulerState.WaitingChallengeEnd;
                        await Task.WhenAny(_poker.WaitAsync(), Task.Delay(delay));
                    }
                }

                // If endtime is after now then something else poked the scheduler awake, reset scheduler logic
                if (endTime != null && endTime > DateTime.UtcNow)
                {
                    continue;
                }

                State = SchedulerState.EndingChallenge;

                // Finish the current challenge
                await _challenges.EndCurrentChallenge();

                // Transfer scores to leaderboard
                await UpdateLeaderboard(current, _solutions.GetSolutions(current.Id, uint.MaxValue));

                // Get the leaderboard for the challenge that just finished and notify everyone
                await NotifyEnd(current, _solutions.GetSolutions(current.Id, uint.MaxValue));

                // Wait for a cooldown period
                State = SchedulerState.WaitingCooldown;
                await Task.WhenAny(_poker.WaitAsync(), Task.Delay(TimeSpan.FromHours(23)));
            }
        }
Exemplo n.º 9
0
        public async Task SubmitSolution([Remainder] string input)
        {
            var code = input.ExtractYololCodeBlock();

            if (code == null)
            {
                await ReplyAsync(@"Failed to parse a yolol program from message - ensure you have enclosed your solution in triple backticks \`\`\`like this\`\`\`");

                return;
            }

            var challenge = await _challenges.GetCurrentChallenge();

            if (challenge == null)
            {
                await ReplyAsync("There is no currently running challenge!");

                return;
            }

            var(success, failure) = await _verification.Verify(challenge, code);

            if (failure != null)
            {
                var message = failure.Type switch {
                    FailureType.ParseFailed => $"Code is not valid Yolol code: {failure.Hint}",
                    FailureType.RuntimeTooLong => "Program took too long to produce a result",
                    FailureType.IncorrectResult => $"Program produced an incorrect value! {failure.Hint}",
                    FailureType.ProgramTooLarge => "Program is too large - it must be 20 lines by 70 characters per line",
                    _ => throw new ArgumentOutOfRangeException()
                };

                await ReplyAsync($"Verification failed! {message}.");
            }
            else if (success != null)
            {
                var solution = await _solutions.GetSolution(Context.User.Id, challenge.Id);

                if (solution.HasValue && success.Score < solution.Value.Score)
                {
                    await ReplyAsync($"Verification complete! You score {success.Score} points. Less than your current best of {solution.Value.Score}");
                }
                else
                {
                    // Get the current top solution
                    var topBefore = await _solutions.GetTopRank(challenge.Id).ToArrayAsync();

                    // Submit this solution
                    await _solutions.SetSolution(new Solution(challenge.Id, Context.User.Id, success.Score, code));

                    var rank = await _solutions.GetRank(challenge.Id, Context.User.Id);

                    var rankNum = uint.MaxValue;
                    if (rank.HasValue)
                    {
                        rankNum = rank.Value.Rank;
                    }
                    await ReplyAsync($"Verification complete! You scored {success.Score} points. You are currently rank {rankNum} for this challenge.");

                    // If this is the top ranking score, and there was a top ranking score before, and it wasn't this user: alert everyone
                    if (rankNum == 1 && topBefore.Length > 0 && topBefore.All(a => a.Solution.UserId != Context.User.Id))
                    {
                        var embed = new EmbedBuilder {
                            Title  = "Rank Alert",
                            Color  = Color.Gold,
                            Footer = new EmbedFooterBuilder().WithText("A Cylon Project")
                        };

                        var self = await _client.GetUserName(Context.User.Id);

                        var prev = (await topBefore.ToAsyncEnumerable().SelectAwait(async a => await _client.GetUserName(a.Solution.UserId)).ToArrayAsync()).Humanize("&");

                        embed.Description = success.Score == topBefore[0].Solution.Score
                            ? $"{self} ties for rank #1"
                            : $"{self} takes rank #1 from {prev}!";

                        await _broadcast.Broadcast(embed.Build());
                    }
                }
            }
            else
            {
                throw new InvalidOperationException("Failed to verify solution (this is a bug, please contact @Martin#2468)");
            }
        }