thx visual studio

This commit is contained in:
Master Kwoth 2016-02-29 05:30:08 +01:00
parent f06ab16a2f
commit 72ecafd552
2 changed files with 990 additions and 975 deletions

View File

@ -1,316 +1,332 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using NadekoBot; using NadekoBot;
using System.Drawing; using System.Drawing;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Collections.Concurrent; using System.Collections.Concurrent;
namespace NadekoBot.Commands { namespace NadekoBot.Commands {
class LoLCommands : DiscordCommand { class LoLCommands : DiscordCommand {
private class CachedChampion { private class CachedChampion {
public System.IO.Stream ImageStream { get; set; } public System.IO.Stream ImageStream { get; set; }
public DateTime AddedAt { get; set; } public DateTime AddedAt { get; set; }
public string Name { get; set; } public string Name { get; set; }
} }
private static List<CachedChampion> CachedChampionImages = new List<CachedChampion>(); private static Dictionary<string, CachedChampion> CachedChampionImages = new Dictionary<string, CachedChampion>();
private readonly object cacheLock = new object(); private readonly object cacheLock = new object();
public LoLCommands() : base() {
Task.Run(async () => { private System.Timers.Timer clearTimer { get; } = new System.Timers.Timer();
while (true) { public LoLCommands() : base() {
lock (cacheLock) { clearTimer.Interval = new TimeSpan(0, 10, 0).TotalMilliseconds;
CachedChampionImages = CachedChampionImages.Where(cc => DateTime.Now - cc.AddedAt < new TimeSpan(1, 0, 0)).ToList(); clearTimer.Start();
} clearTimer.Elapsed += (s, e) => {
await Task.Delay(new TimeSpan(0, 10, 0)); try {
} lock (cacheLock)
}); CachedChampionImages = CachedChampionImages
} .Where(kvp => DateTime.Now - kvp.Value.AddedAt > new TimeSpan(1, 0, 0))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
string[] trashTalk = new[] { "Better ban your counters. You are going to carry the game anyway.", }
"Go with the flow. Don't think. Just ban one of these.", catch { }
"DONT READ BELOW! Ban Urgot mid OP 100%. Im smurf Diamond 1.", };
"Ask your teammates what would they like to play, and ban that.", }
"If you consider playing teemo, do it. If you consider teemo, you deserve him.",
"Doesn't matter what you ban really. Enemy will ban your main and you will lose." }; string[] trashTalk = new[] { "Better ban your counters. You are going to carry the game anyway.",
"Go with the flow. Don't think. Just ban one of these.",
public override Func<CommandEventArgs, Task> DoFunc() { "DONT READ BELOW! Ban Urgot mid OP 100%. Im smurf Diamond 1.",
throw new NotImplementedException(); "Ask your teammates what would they like to play, and ban that.",
} "If you consider playing teemo, do it. If you consider teemo, you deserve him.",
"Doesn't matter what you ban really. Enemy will ban your main and you will lose." };
class MatchupModel {
public int Games { get; set; } public override Func<CommandEventArgs, Task> DoFunc() {
public float WinRate { get; set; } throw new NotImplementedException();
[Newtonsoft.Json.JsonProperty("key")] }
public string Name { get; set; }
public float StatScore { get; set; } class MatchupModel {
} public int Games { get; set; }
public float WinRate { get; set; }
public override void Init(CommandGroupBuilder cgb) { [Newtonsoft.Json.JsonProperty("key")]
cgb.CreateCommand("~lolchamp") public string Name { get; set; }
.Description("Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role.\n**Usage**:~lolchamp Riven or ~lolchamp Annie sup") public float StatScore { get; set; }
.Parameter("champ", ParameterType.Required) }
.Parameter("position", ParameterType.Unparsed)
.Do(async e => { public override void Init(CommandGroupBuilder cgb) {
try { cgb.CreateCommand("~lolchamp")
//get role .Description("Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role.\n**Usage**:~lolchamp Riven or ~lolchamp Annie sup")
string role = ResolvePos(e.GetArg("position")); .Parameter("champ", ParameterType.Required)
var name = e.GetArg("champ").Replace(" ", ""); .Parameter("position", ParameterType.Unparsed)
CachedChampion champ; .Do(async e => {
lock (cacheLock) { try {
champ = CachedChampionImages.Where(cc => cc.Name == name.ToLower()).FirstOrDefault(); //get role
} string role = ResolvePos(e.GetArg("position"));
if (champ != null) { string resolvedRole = role;
Console.WriteLine("Sending lol image from cache."); var name = e.GetArg("champ").Replace(" ", "");
champ.ImageStream.Position = 0; CachedChampion champ = null;
await e.Channel.SendFile("champ.png", champ.ImageStream); lock (cacheLock) {
return; CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ);
} }
var allData = JArray.Parse(await Classes.SearchHelper.GetResponseAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.creds.LOLAPIKey}")); if (champ != null) {
JToken data = null; Console.WriteLine("Sending lol image from cache.");
if (role != null) { champ.ImageStream.Position = 0;
for (int i = 0; i < allData.Count; i++) { await e.Channel.SendFile("champ.png", champ.ImageStream);
if (allData[i]["role"].ToString().Equals(role)) { return;
data = allData[i]; }
break; var allData = JArray.Parse(await Classes.SearchHelper.GetResponseAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.creds.LOLAPIKey}"));
} JToken data = null;
} if (role != null) {
if (data == null) { for (int i = 0; i < allData.Count; i++) {
await e.Channel.SendMessage("💢 Data for that role does not exist."); if (allData[i]["role"].ToString().Equals(role)) {
return; data = allData[i];
} break;
} }
else { }
data = allData[0]; if (data == null) {
role = allData[0]["role"].ToString(); await e.Channel.SendMessage("💢 Data for that role does not exist.");
} return;
//name = data["title"].ToString(); }
// get all possible roles, and "select" the shown one }
var roles = new string[allData.Count]; else {
for (int i = 0; i < allData.Count; i++) { data = allData[0];
roles[i] = allData[i]["role"].ToString(); role = allData[0]["role"].ToString();
if (roles[i] == role) resolvedRole = ResolvePos(role);
roles[i] = ">" + roles[i] + "<"; }
} lock (cacheLock) {
var general = JArray.Parse(await Classes.SearchHelper.GetResponseAsync($"http://api.champion.gg/stats/champs/{name}?api_key={NadekoBot.creds.LOLAPIKey}")) CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ);
.Where(jt => jt["role"].ToString() == role) }
.FirstOrDefault()?["general"]; if (champ != null) {
if (general == null) { Console.WriteLine("Sending lol image from cache.");
Console.WriteLine("General is null."); champ.ImageStream.Position = 0;
return; await e.Channel.SendFile("champ.png", champ.ImageStream);
} return;
//get build data for this role }
var buildData = data["items"]["mostGames"]["items"]; //name = data["title"].ToString();
var items = new string[6]; // get all possible roles, and "select" the shown one
for (int i = 0; i < 6; i++) { var roles = new string[allData.Count];
items[i] = buildData[i]["id"].ToString(); for (int i = 0; i < allData.Count; i++) {
} roles[i] = allData[i]["role"].ToString();
if (roles[i] == role)
//get matchup data to show counters and countered champions roles[i] = ">" + roles[i] + "<";
var matchupDataIE = data["matchups"].ToObject<List<MatchupModel>>(); }
var general = JArray.Parse(await Classes.SearchHelper.GetResponseAsync($"http://api.champion.gg/stats/champs/{name}?api_key={NadekoBot.creds.LOLAPIKey}"))
var matchupData = matchupDataIE.OrderBy(m => m.StatScore).ToArray(); .Where(jt => jt["role"].ToString() == role)
.FirstOrDefault()?["general"];
var countered = new[] { matchupData[0].Name, matchupData[1].Name, matchupData[2].Name }; if (general == null) {
var counters = new[] { matchupData[matchupData.Length - 1].Name, matchupData[matchupData.Length - 2].Name, matchupData[matchupData.Length - 3].Name }; Console.WriteLine("General is null.");
return;
//get runes data }
var runesJArray = data["runes"]["mostGames"]["runes"] as JArray; //get build data for this role
var runes = string.Join("\n", runesJArray.OrderBy(jt => int.Parse(jt["number"].ToString())).Select(jt => jt["number"].ToString() + "x" + jt["name"])); var buildData = data["items"]["mostGames"]["items"];
var items = new string[6];
// get masteries data for (int i = 0; i < 6; i++) {
items[i] = buildData[i]["id"].ToString();
var masteries = (data["masteries"]["mostGames"]["masteries"] as JArray); }
//get skill order data<API_KEY> //get matchup data to show counters and countered champions
var matchupDataIE = data["matchups"].ToObject<List<MatchupModel>>();
var orderArr = (data["skills"]["mostGames"]["order"] as JArray);
var matchupData = matchupDataIE.OrderBy(m => m.StatScore).ToArray();
//todo save this for at least 1 hour
Image img = Image.FromFile("data/lol/bg.png"); var countered = new[] { matchupData[0].Name, matchupData[1].Name, matchupData[2].Name };
using (Graphics g = Graphics.FromImage(img)) { var counters = new[] { matchupData[matchupData.Length - 1].Name, matchupData[matchupData.Length - 2].Name, matchupData[matchupData.Length - 3].Name };
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
//g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; //get runes data
int statsFontSize = 15; var runesJArray = data["runes"]["mostGames"]["runes"] as JArray;
int margin = 5; var runes = string.Join("\n", runesJArray.OrderBy(jt => int.Parse(jt["number"].ToString())).Select(jt => jt["number"].ToString() + "x" + jt["name"]));
int imageSize = 75;
var normalFont = new Font("Monaco", 8, FontStyle.Regular); // get masteries data
var smallFont = new Font("Monaco", 7, FontStyle.Regular);
//draw champ image var masteries = (data["masteries"]["mostGames"]["masteries"] as JArray);
var champName = data["key"].ToString().Replace(" ", "");
//get skill order data<API_KEY>
g.DrawImage(GetImage(champName), new Rectangle(margin, margin, imageSize, imageSize));
//draw champ name var orderArr = (data["skills"]["mostGames"]["order"] as JArray);
if (champName == "MonkeyKing")
champName = "Wukong"; //todo save this for at least 1 hour
g.DrawString($"{champName}", new Font("Times New Roman", 24, FontStyle.Regular), Brushes.WhiteSmoke, margin + imageSize + margin, margin); Image img = Image.FromFile("data/lol/bg.png");
//draw champ surname using (Graphics g = Graphics.FromImage(img)) {
//todo g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
//draw skill order //g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
float orderFormula = 120 / orderArr.Count; int statsFontSize = 15;
float orderVerticalSpacing = 10; int margin = 5;
for (int i = 0; i < orderArr.Count; i++) { int imageSize = 75;
float orderX = margin + margin + imageSize + orderFormula * i + i; var normalFont = new Font("Monaco", 8, FontStyle.Regular);
float orderY = margin + 35; var smallFont = new Font("Monaco", 7, FontStyle.Regular);
string spellName = orderArr[i].ToString().ToLowerInvariant(); //draw champ image
var champName = data["key"].ToString().Replace(" ", "");
if (spellName == "w")
orderY += orderVerticalSpacing; g.DrawImage(GetImage(champName), new Rectangle(margin, margin, imageSize, imageSize));
else if (spellName == "e") //draw champ name
orderY += orderVerticalSpacing * 2; if (champName == "MonkeyKing")
else if (spellName == "r") champName = "Wukong";
orderY += orderVerticalSpacing * 3; g.DrawString($"{champName}", new Font("Times New Roman", 24, FontStyle.Regular), Brushes.WhiteSmoke, margin + imageSize + margin, margin);
//draw champ surname
g.DrawString(spellName.ToUpperInvariant(), new Font("Monaco", 7), Brushes.LimeGreen, orderX, orderY); //todo
} //draw skill order
//draw roles float orderFormula = 120 / orderArr.Count;
g.DrawString("Roles: " + string.Join(", ", roles), normalFont, Brushes.WhiteSmoke, margin, margin + imageSize + margin); float orderVerticalSpacing = 10;
for (int i = 0; i < orderArr.Count; i++) {
//draw average stats float orderX = margin + margin + imageSize + orderFormula * i + i;
g.DrawString( float orderY = margin + 35;
$@" Average Stats string spellName = orderArr[i].ToString().ToLowerInvariant();
Kills: {general["kills"]} CS: {general["minionsKilled"]} if (spellName == "w")
Deaths: {general["deaths"]} Win: {general["winPercent"]}% orderY += orderVerticalSpacing;
Assists: {general["assists"]} Ban: {general["banRate"]}% else if (spellName == "e")
", normalFont, Brushes.WhiteSmoke, img.Width - 150, margin); orderY += orderVerticalSpacing * 2;
//draw masteries else if (spellName == "r")
g.DrawString($"Masteries: {string.Join(" / ", masteries?.Select(jt => jt["total"]))}", normalFont, Brushes.WhiteSmoke, margin, margin + imageSize + margin + 20); orderY += orderVerticalSpacing * 3;
//draw runes
g.DrawString($"{runes}", smallFont, Brushes.WhiteSmoke, margin, margin + imageSize + margin + 40); g.DrawString(spellName.ToUpperInvariant(), new Font("Monaco", 7), Brushes.LimeGreen, orderX, orderY);
//draw counters }
g.DrawString($"Best against", smallFont, Brushes.WhiteSmoke, margin, img.Height - imageSize + margin); //draw roles
int smallImgSize = 50; g.DrawString("Roles: " + string.Join(", ", roles), normalFont, Brushes.WhiteSmoke, margin, margin + imageSize + margin);
for (int i = 0; i < counters.Length; i++) { //draw average stats
g.DrawImage(GetImage(counters[i]), g.DrawString(
new Rectangle(i * (smallImgSize + margin) + margin, img.Height - smallImgSize - margin, $@" Average Stats
smallImgSize,
smallImgSize)); Kills: {general["kills"]} CS: {general["minionsKilled"]}
} Deaths: {general["deaths"]} Win: {general["winPercent"]}%
//draw countered by Assists: {general["assists"]} Ban: {general["banRate"]}%
g.DrawString($"Worst against", smallFont, Brushes.WhiteSmoke, img.Width - 3 * (smallImgSize + margin), img.Height - imageSize + margin); ", normalFont, Brushes.WhiteSmoke, img.Width - 150, margin);
//draw masteries
for (int i = 0; i < countered.Length; i++) { g.DrawString($"Masteries: {string.Join(" / ", masteries?.Select(jt => jt["total"]))}", normalFont, Brushes.WhiteSmoke, margin, margin + imageSize + margin + 20);
int j = countered.Length - i; //draw runes
g.DrawImage(GetImage(countered[i]), g.DrawString($"{runes}", smallFont, Brushes.WhiteSmoke, margin, margin + imageSize + margin + 40);
new Rectangle(img.Width - (j * (smallImgSize + margin) + margin), img.Height - smallImgSize - margin, //draw counters
smallImgSize, g.DrawString($"Best against", smallFont, Brushes.WhiteSmoke, margin, img.Height - imageSize + margin);
smallImgSize)); int smallImgSize = 50;
}
//draw item build for (int i = 0; i < counters.Length; i++) {
g.DrawString("Popular build", normalFont, Brushes.WhiteSmoke, img.Width - (3 * (smallImgSize + margin) + margin), 77); g.DrawImage(GetImage(counters[i]),
new Rectangle(i * (smallImgSize + margin) + margin, img.Height - smallImgSize - margin,
for (int i = 0; i < 6; i++) { smallImgSize,
var inverse_i = 5 - i; smallImgSize));
var j = inverse_i % 3 + 1; }
var k = inverse_i / 3; //draw countered by
g.DrawImage(GetImage(items[i], GetImageType.Item), g.DrawString($"Worst against", smallFont, Brushes.WhiteSmoke, img.Width - 3 * (smallImgSize + margin), img.Height - imageSize + margin);
new Rectangle(img.Width - (j * (smallImgSize + margin) + margin), 92 + k * (smallImgSize + margin),
smallImgSize, for (int i = 0; i < countered.Length; i++) {
smallImgSize)); int j = countered.Length - i;
} g.DrawImage(GetImage(countered[i]),
} new Rectangle(img.Width - (j * (smallImgSize + margin) + margin), img.Height - smallImgSize - margin,
var cachedChamp = new CachedChampion { AddedAt = DateTime.Now, ImageStream = img.ToStream(System.Drawing.Imaging.ImageFormat.Png), Name = name.ToLower() }; smallImgSize,
CachedChampionImages.Add(cachedChamp); smallImgSize));
await e.Channel.SendFile(data["title"] + "_stats.png", cachedChamp.ImageStream); }
} //draw item build
catch (Exception ex) { g.DrawString("Popular build", normalFont, Brushes.WhiteSmoke, img.Width - (3 * (smallImgSize + margin) + margin), 77);
await e.Channel.SendMessage("💢 Failed retreiving data for that champion.");
return; for (int i = 0; i < 6; i++) {
} var inverse_i = 5 - i;
}); var j = inverse_i % 3 + 1;
var k = inverse_i / 3;
cgb.CreateCommand("~lolban") g.DrawImage(GetImage(items[i], GetImageType.Item),
.Description("Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time.") new Rectangle(img.Width - (j * (smallImgSize + margin) + margin), 92 + k * (smallImgSize + margin),
.Do(async e => { smallImgSize,
smallImgSize));
int showCount = 6; }
//http://api.champion.gg/stats/champs/mostBanned?api_key=YOUR_API_TOKEN&page=1&limit=2 }
try { var cachedChamp = new CachedChampion { AddedAt = DateTime.Now, ImageStream = img.ToStream(System.Drawing.Imaging.ImageFormat.Png), Name = name.ToLower() + "_" + resolvedRole };
var data = JObject.Parse( CachedChampionImages.Add(cachedChamp.Name, cachedChamp);
await Classes await e.Channel.SendFile(data["title"] + "_stats.png", cachedChamp.ImageStream);
.SearchHelper }
.GetResponseAsync($"http://api.champion.gg/stats/champs/mostBanned?api_key={NadekoBot.creds.LOLAPIKey}&page=1&limit={showCount}"))["data"] as JArray; catch (Exception ex) {
await e.Channel.SendMessage("💢 Failed retreiving data for that champion.");
StringBuilder sb = new StringBuilder(); return;
sb.AppendLine($"**Showing {showCount} top banned champions.**"); }
sb.AppendLine($"`{trashTalk[new Random().Next(0, trashTalk.Length)]}`"); });
for (int i = 0; i < data.Count; i++) {
if (i % 2 == 0 && i != 0) cgb.CreateCommand("~lolban")
sb.AppendLine(); .Description("Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time.")
sb.Append($"`{i + 1}.` **{data[i]["name"]}** "); .Do(async e => {
//sb.AppendLine($" ({data[i]["general"]["banRate"]}%)");
} int showCount = 6;
//http://api.champion.gg/stats/champs/mostBanned?api_key=YOUR_API_TOKEN&page=1&limit=2
await e.Channel.SendMessage(sb.ToString()); try {
} var data = JObject.Parse(
catch (Exception ex) { await Classes
await e.Channel.SendMessage($"Fail:\n{ex}"); .SearchHelper
} .GetResponseAsync($"http://api.champion.gg/stats/champs/mostBanned?api_key={NadekoBot.creds.LOLAPIKey}&page=1&limit={showCount}"))["data"] as JArray;
});
} StringBuilder sb = new StringBuilder();
enum GetImageType { sb.AppendLine($"**Showing {showCount} top banned champions.**");
Champion, sb.AppendLine($"`{trashTalk[new Random().Next(0, trashTalk.Length)]}`");
Item for (int i = 0; i < data.Count; i++) {
} if (i % 2 == 0 && i != 0)
private Image GetImage(string id, GetImageType imageType = GetImageType.Champion) { sb.AppendLine();
try { sb.Append($"`{i + 1}.` **{data[i]["name"]}** ");
switch (imageType) { //sb.AppendLine($" ({data[i]["general"]["banRate"]}%)");
case GetImageType.Champion: }
return Image.FromFile($"data/lol/champions/{id}.png");
case GetImageType.Item: await e.Channel.SendMessage(sb.ToString());
default: }
return Image.FromFile($"data/lol/items/{id}.png"); catch (Exception ex) {
} await e.Channel.SendMessage($"Fail:\n{ex}");
} }
catch (Exception) { });
return Image.FromFile("data/lol/_ERROR.png"); }
} enum GetImageType {
} Champion,
Item
private string ResolvePos(string pos) { }
if (string.IsNullOrWhiteSpace(pos)) private Image GetImage(string id, GetImageType imageType = GetImageType.Champion) {
return null; try {
switch (pos.ToLowerInvariant()) { switch (imageType) {
case "m": case GetImageType.Champion:
case "mid": return Image.FromFile($"data/lol/champions/{id}.png");
case "midorfeed": case GetImageType.Item:
case "midd": default:
case "middle": return Image.FromFile($"data/lol/items/{id}.png");
return "Middle"; }
case "top": }
case "topp": catch (Exception) {
case "t": return Image.FromFile("data/lol/_ERROR.png");
case "toporfeed": }
return "Top"; }
case "j":
case "jun": private string ResolvePos(string pos) {
case "jungl": if (string.IsNullOrWhiteSpace(pos))
case "jungle": return null;
return "Jungle"; switch (pos.ToLowerInvariant()) {
case "a": case "m":
case "ad": case "mid":
case "adc": case "midorfeed":
case "carry": case "midd":
case "ad carry": case "middle":
case "adcarry": return "Middle";
case "c": case "top":
return "ADC"; case "topp":
case "s": case "t":
case "sup": case "toporfeed":
case "supp": return "Top";
case "support": case "j":
return "Support"; case "jun":
default: case "jungl":
return pos; case "jungle":
} return "Jungle";
} case "a":
} case "ad":
} case "adc":
case "carry":
case "ad carry":
case "adcarry":
case "c":
return "ADC";
case "s":
case "sup":
case "supp":
case "support":
return "Support";
default:
return pos;
}
}
}
}

File diff suppressed because it is too large Load Diff