public static async Task UpdateStandingsAsync()
        {
            DiscordChannel standingChannel = await Client.GetChannelAsync(592230066654674945);

            foreach (DiscordMessage discordMessage in await standingChannel.GetMessagesAsync())
            {
                await standingChannel.DeleteMessageAsync(discordMessage, "Standings update.");
            }

            SdlPlayer[] players = await MySqlClient.RetrieveAllSdlPlayers();

            List <SdlPlayer> orderedPlayers = players
                                              .Where(x => standingChannel.Guild.Members.Any(y =>
                                                                                            y.Id == x.DiscordId &&
                                                                                            MySqlClient.CheckHasPlayedSet(x).Result&&
                                                                                            y.Roles.Any(z =>
                                                                                                        z.Name.Equals("player", StringComparison.InvariantCultureIgnoreCase))))
                                              .OrderByDescending(x => x.PowerLevel).ToList();

            var playerStandings = orderedPlayers.Select(x => new { Player = x, Rank = orderedPlayers.FindLastIndex(y => y.PowerLevel == x.PowerLevel) + 1 });

            List <DiscordEmbedBuilder> standingEmbeds = new List <DiscordEmbedBuilder>
            {
                new DiscordEmbedBuilder().WithDescription("").WithColor(Color.Gold)
            };

            int startStanding = 1;
            int endStanding   = 0;

            foreach (var playerStanding in playerStandings)
            {
                string standingLine = $"\n{playerStanding.Rank}: {playerStanding.Player.DiscordId.ToUserMention()} [{playerStanding.Player.PowerLevel}]";

                if (standingEmbeds.Last().Description.Length + standingLine.Length > 2048)
                {
                    standingEmbeds.Last().Title = $"Standings ({startStanding} - {endStanding})";

                    standingEmbeds.Add(new DiscordEmbedBuilder().WithDescription("").WithColor(Color.Silver));

                    startStanding = endStanding + 1;
                    endStanding   = startStanding;
                }

                standingEmbeds.Last().Description += standingLine;

                endStanding++;
            }

            standingEmbeds.Last().Title = $"Standings ({startStanding} - {endStanding})";

            foreach (DiscordEmbedBuilder standingEmbed in standingEmbeds)
            {
                await standingChannel.SendMessageAsync(embed : standingEmbed.Build());
            }
        }
示例#2
0
        public async Task Profile(CommandContext ctx, [RemainingText] DiscordMember user = null)
        {
            try
            {
                if (user == null)
                {
                    user = ctx.Member;
                }

                SdlPlayer player;
                try
                {
                    player = await MySqlClient.RetrieveSdlPlayer(user.Id);
                }
                catch (Exception e)
                {
                    Logger.Warn(e);

                    /*if (e is SdlAirTableException airTableException)
                     *  await airTableException.Message;*/

                    throw;
                }

                await ctx.TriggerTypingAsync();

                Font powerFont      = KarlaFontFamily.CreateFont(160, FontStyle.Bold);
                Font nameFont       = KarlaFontFamily.CreateFont(80, FontStyle.Bold);
                Font winRateFont    = KarlaFontFamily.CreateFont(100, FontStyle.Bold);
                Font switchCodeFont = KarlaItalicFontFamily.CreateFont(50, FontStyle.Italic);
                Font classFont      = KarlaFontFamily.CreateFont(180, FontStyle.Bold);
                Font classNameFont  = KarlaFontFamily.CreateFont(26, FontStyle.Bold);
                Font roleFont       = KarlaFontFamily.CreateFont(100, FontStyle.Bold);
                Font placementFont  = KarlaFontFamily.CreateFont(113, FontStyle.Bold);
                Font ordinalFont    = KarlaFontFamily.CreateFont(57, FontStyle.Bold);

                WebClient webClient = new WebClient();

                string avatarUrl = string.IsNullOrWhiteSpace(user.GetAvatarUrl(ImageFormat.Png)) ? user.DefaultAvatarUrl : user.GetAvatarUrl(ImageFormat.Png);

                byte[] avatarBytes = await webClient.DownloadDataTaskAsync(avatarUrl);

                using (Image <Rgba32> image = Image.Load(Path.Combine(Globals.AppPath, "Data", "img", "profile-template.png")))
                {
                    using Image <Rgba32> rankImage   = new Image <Rgba32>(225, 225);
                    using Image <Rgba32> avatarImage = Image.Load(avatarBytes);
                    using Image <Rgba32> roleImage   = new Image <Rgba32>(455, 115);
                    using MemoryStream ms = new MemoryStream();

                    string name       = player.Nickname.ToUpper();
                    string powerLevel = Math.Round(player.PowerLevel, 1).ToString(CultureInfo.InvariantCulture);

                    SizeF nameTextSize = TextMeasurer.Measure(name, new RendererOptions(nameFont));

                    if (nameTextSize.Width > 700)
                    {
                        float nameScalingFactor = 700 / nameTextSize.Width;
                        nameFont = KarlaFontFamily.CreateFont(nameFont.Size * nameScalingFactor);
                    }

                    IPathCollection nameTextGlyphs = TextBuilder.GenerateGlyphs(name,
                                                                                new PointF(445, 45), new RendererOptions(nameFont));

                    SizeF powerLevelSize = TextMeasurer.Measure(powerLevel, new RendererOptions(powerFont));

                    float powerYDifference = 0;

                    if (powerLevelSize.Width > 480)
                    {
                        float powerScalingFactor = 480 / powerLevelSize.Width;
                        powerFont = KarlaFontFamily.CreateFont(powerFont.Size * powerScalingFactor, FontStyle.Bold);

                        powerYDifference = powerLevelSize.Height - TextMeasurer.Measure(powerLevel, new RendererOptions(powerFont)).Height;
                    }

                    IPathCollection powerTextGlyphs = TextBuilder.GenerateGlyphs(powerLevel,
                                                                                 new PointF(445, 110 + powerYDifference), new RendererOptions(powerFont));

                    IPathCollection switchCodeGlyphs = TextBuilder.GenerateGlyphs(player.SwitchFriendCode,
                                                                                  new PointF(420, 987), new RendererOptions(switchCodeFont));

                    // When centering, this is for if everything is off by the same amount.
                    const float offset = 0;

                    string splatZonesWr = player.WinRates.ContainsKey(GameMode.SplatZones) ?
                                          $"{player.WinRates[GameMode.SplatZones]:P0}" :
                                          "N/A";

                    SizeF szWrSize = TextMeasurer.Measure(splatZonesWr, new RendererOptions(winRateFont));

                    float szWrX = 379 + offset + (119F - szWrSize.Width / 2);

                    IPathCollection splatZonesGlyphs = TextBuilder.GenerateGlyphs(
                        splatZonesWr, new PointF(szWrX, 420), new RendererOptions(winRateFont));

                    string rainmakerWr = player.WinRates.ContainsKey(GameMode.Rainmaker) ?
                                         $"{player.WinRates[GameMode.Rainmaker]:P0}" :
                                         "N/A";

                    SizeF rmWrSize = TextMeasurer.Measure(rainmakerWr, new RendererOptions(winRateFont));

                    float rmWrX = 379 + offset + (119F - rmWrSize.Width / 2);

                    IPathCollection rainmakerGlyphs = TextBuilder.GenerateGlyphs(
                        rainmakerWr, new PointF(rmWrX, 587), new RendererOptions(winRateFont));

                    string towerControlWr = player.WinRates.ContainsKey(GameMode.TowerControl) ?
                                            $"{player.WinRates[GameMode.TowerControl]:P0}" :
                                            "N/A";

                    SizeF tcWrSize = TextMeasurer.Measure(towerControlWr, new RendererOptions(winRateFont));

                    float tcWrX = 1005 + offset + (119F - tcWrSize.Width / 2);

                    IPathCollection towerControlGlyphs = TextBuilder.GenerateGlyphs(
                        towerControlWr, new PointF(tcWrX, 420), new RendererOptions(winRateFont));

                    string clamBlitzWr = player.WinRates.ContainsKey(GameMode.ClamBlitz) ?
                                         $"{player.WinRates[GameMode.ClamBlitz]:P0}" :
                                         "N/A";

                    SizeF cbWrSize = TextMeasurer.Measure(clamBlitzWr, new RendererOptions(winRateFont));

                    float cbWrX = 1005 + offset + (119F - cbWrSize.Width / 2);

                    IPathCollection clamBlitzGlyphs = TextBuilder.GenerateGlyphs(
                        clamBlitzWr, new PointF(cbWrX, 587), new RendererOptions(winRateFont));

                    string overallWrText = Math.Abs(player.OverallWinRate + 1) < 0.1
                        ? "N/A"
                        : $"{player.OverallWinRate:P0}";

                    SizeF overallWrSize = TextMeasurer.Measure(overallWrText, new RendererOptions(winRateFont));

                    float overallWrX = 740 + offset + (119F - overallWrSize.Width / 2);

                    IPathCollection overallGlyphs = TextBuilder.GenerateGlyphs(
                        overallWrText, new PointF(overallWrX, 755), new RendererOptions(winRateFont));

                    Rgba32 classColor;
                    string classText;

                    if (player.PowerLevel >= 2200)
                    {
                        classColor = new Rgba32(255, 70, 75);
                        classText  = "1";
                    }
                    else if (player.PowerLevel >= 2000)
                    {
                        classColor = new Rgba32(255, 190, 52);
                        classText  = "2";
                    }
                    else if (player.PowerLevel >= 1800)
                    {
                        classColor = new Rgba32(61, 255, 99);
                        classText  = "3";
                    }
                    else
                    {
                        classColor = new Rgba32(21, 205, 227);
                        classText  = "4";
                    }

                    SizeF classSize = TextMeasurer.Measure(classText, new RendererOptions(classFont));

                    float classX = 1340 + ((float)rankImage.Width / 2 - classSize.Width / 2);

                    IPathCollection classNameGlyphs =
                        TextBuilder.GenerateGlyphs("CLASS", new PointF(1414.32F, 70), new RendererOptions(classNameFont));

                    IPathCollection classGlyphs =
                        TextBuilder.GenerateGlyphs(classText, new PointF(classX, 67.57F),
                                                   new RendererOptions(classFont));

                    Rgba32 roleColor;

                    string role = player.RoleOne ?? "Flex";

                    switch (role.ToLower())
                    {
                    case "back":
                        roleColor = Rgba32.FromHex("#4BDFFA");
                        break;

                    case "front":
                        roleColor = Rgba32.FromHex("#EB5F5F");
                        break;

                    case "mid":
                        roleColor = Rgba32.FromHex("#61E87B");
                        break;

                    case "flex":
                        roleColor = Rgba32.RebeccaPurple;
                        break;

                    default:
                        roleColor = Rgba32.Black;
                        break;
                    }

                    role = role.ToUpper();

                    SizeF roleNameSize = TextMeasurer.Measure(role, new RendererOptions(roleFont));

                    float roleNameX = (float)roleImage.Width / 2 - roleNameSize.Width / 2;
                    float roleNameY = (float)roleImage.Height / 2 - roleNameSize.Height / 2 - 10;

                    IPathCollection roleGlyphs = TextBuilder.GenerateGlyphs(role, new PointF(roleNameX, roleNameY),
                                                                            new RendererOptions(roleFont));

                    SdlPlayer[] players = await MySqlClient.RetrieveAllSdlPlayers();

                    List <SdlPlayer> orderedPlayers = players
                                                      .Where(x => ctx.Guild.Members.Any(y =>
                                                                                        y.Id == x.DiscordId &&
                                                                                        MySqlClient.CheckHasPlayedSet(x).Result&&
                                                                                        y.Roles.Any(z =>
                                                                                                    z.Name.Equals("player", StringComparison.InvariantCultureIgnoreCase))))
                                                      .OrderByDescending(x => x.PowerLevel).ToList();

                    var playerStandings = orderedPlayers.Select(x => new { Player = x, Rank = orderedPlayers.FindLastIndex(y => y.PowerLevel == x.PowerLevel) + 1 }).ToList();

                    string ordinal   = "";
                    int    placement = 0;

                    if (playerStandings.All(x => x.Player != player))
                    {
                        await ctx.RespondAsync("Note that you will not have a standing until you play a set.");
                    }
                    else
                    {
                        placement = playerStandings.First(x => x.Player == player).Rank;
                        ordinal   = placement.GetOrdinal();
                    }

                    SizeF placementSize =
                        TextMeasurer.Measure(placement == 0 ? "N/A" : placement.ToString(), new RendererOptions(placementFont));
                    SizeF ordinalSize =
                        TextMeasurer.Measure(ordinal, new RendererOptions(ordinalFont));

                    float standingsWidth =
                        placementSize.Width + ordinalSize.Width;

                    float placementX = 949 + (347 / 2F - standingsWidth / 2F);

                    IPathCollection placementGlyphs = TextBuilder.GenerateGlyphs(placement == 0 ? "N/A" : placement.ToString(),
                                                                                 new PointF(placementX, 140), new RendererOptions(placementFont));

                    float ordinalX = placementX + placementSize.Width;
                    float ordinalY = 140 + placementSize.Height - ordinalSize.Height - 5;

                    IPathCollection ordinalGlyphs = TextBuilder.GenerateGlyphs(ordinal, new PointF(ordinalX, ordinalY),
                                                                               new RendererOptions(ordinalFont));

                    TextGraphicsOptions textGraphicsOptions = new TextGraphicsOptions(true);

                    rankImage.Mutate(e => e
                                     .Fill(classColor)
                                     .Apply(f => ApplyRoundedCorners(f, 30))
                                     );

                    avatarImage.Mutate(e => e
                                       .Resize(new Size(268, 268))
                                       .Apply(img => ApplyRoundedCorners(img, 40))
                                       );

                    roleImage.Mutate(e => e
                                     .Fill(roleColor)
                                     .Apply(f => ApplyRoundedCorners(f, 30))
                                     .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.White, roleGlyphs)
                                     );

                    image.Mutate(e => e
                                 .DrawImage(avatarImage, new Point(48, 32), 1)
                                 .DrawImage(rankImage, new Point(1340, 50), 1)
                                 .DrawImage(roleImage, new Point(1111, 755), 1)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, powerTextGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, nameTextGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, switchCodeGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, splatZonesGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, rainmakerGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, towerControlGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, clamBlitzGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, overallGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.White, classGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.White, classNameGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, placementGlyphs)
                                 .Fill((GraphicsOptions)textGraphicsOptions, Rgba32.Black, ordinalGlyphs)
                                 );

                    image.SaveAsPng(ms);

                    using MemoryStream memory = new MemoryStream(ms.GetBuffer());
                    await ctx.Channel.SendFileAsync(memory, "profile.png");
                }

                Configuration.Default.MemoryAllocator.ReleaseRetainedResources();
            }
            catch (Exception e)
            {
                Logger.Error(e);
                throw;
            }
        }