Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions DotaLass/API/Enums/RankTier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace DotaLass.API.Enums
{
public enum RankTier
{
Herald1 = 11,
Herald2 = 12,
Herald3 = 13,
Herald4 = 14,
Herald5 = 15,
Guardian1 = 21,
Guardian2 = 22,
Guardian3 = 23,
Guardian4 = 24,
Guardian5 = 25,
Crusader1 = 31,
Crusader2 = 32,
Crusader3 = 33,
Crusader4 = 34,
Crusader5 = 35,
Archon1 = 41,
Archon2 = 42,
Archon3 = 43,
Archon4 = 44,
Archon5 = 45,
Legend1 = 51,
Legend2 = 52,
Legend3 = 53,
Legend4 = 54,
Legend5 = 55,
Ancient1 = 61,
Ancient2 = 62,
Ancient3 = 63,
Ancient4 = 64,
Ancient5 = 65,
Divine1 = 71,
Divine2 = 72,
Divine3 = 73,
Divine4 = 74,
Divine5 = 75,
Immortal = 80
}
}
56 changes: 56 additions & 0 deletions DotaLass/API/OpenDotaAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
Expand All @@ -12,6 +13,8 @@ namespace DotaLass.API
{
public static class OpenDotaAPI
{
private static readonly Dictionary<string, PlayerPeer[]> PlayerPeersCache = new Dictionary<string, PlayerPeer[]>();

public static PlayerData GetPlayerData(string playerID)
{
string result = RequestHandler.GET($"https://api.opendota.com/api/players/{playerID}");
Expand All @@ -22,6 +25,59 @@ public static PlayerData GetPlayerData(string playerID)
return null;
}

public static PlayerPeer[] GetPlayerPeers(string playerID)
{
if (PlayerPeersCache.ContainsKey(playerID))
return PlayerPeersCache[playerID];
var requestString = $@"https://api.opendota.com/api/players/{playerID}/peers?sort=""with_games""";
var result = RequestHandler.GET(requestString);
if (result != null)
{
PlayerPeersCache.Add(playerID, JsonConvert.DeserializeObject<PlayerPeer[]>(result));
return PlayerPeersCache[playerID];
}
else
return null;
}

public static List<List<string>> GetPlayersPartiesList(List<string> playersIds)
{
if(playersIds == null)
return new List<List<string>>();
//var friends = playersIds.Select(e => Tuple.Create(e, GetPlayerPeers(e))).ToArray();
var friends = playersIds.AsParallel().Select(e => Tuple.Create(e, GetPlayerPeers(e))).ToArray();
var playerIdToPeers = friends.ToDictionary(e => e.Item1,
e => e.Item2
.Where(x => x.WithGames >= 5 && x.AgainstGames <= 2 && playersIds.Contains(x.AccountId.ToString()))
.Select(x => x.AccountId.ToString()).ToArray());
var result = new List<List<string>>();
var hashSet = new HashSet<string>();
foreach (var playerId in playersIds)
{
if (hashSet.Contains(playerId))
continue;
var group = GetFullSubset(playerIdToPeers, new[] {playerId}).ToList();
if(group.Count < 2)
continue;
result.Add(group);
foreach (var p in group)
{
hashSet.Add(p);
}
}

return result;
}

private static IEnumerable<string> GetFullSubset(IDictionary<string, string[]> lookup, string[] subset, int iteration = 0)
{
if (iteration >= 4)
return subset;

subset = subset.Concat(subset.SelectMany(element => lookup[element])).Distinct().ToArray();
return GetFullSubset(lookup, subset, iteration+1);
}

public static Match[] GetPlayerMatches(string playerID, int limit, int days, int lobbyType)
{
string requestString = $@"https://api.opendota.com/api/players/{playerID}/matches?limit={limit}";
Expand Down
1 change: 1 addition & 0 deletions DotaLass/API/Outputs/PlayerData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class PlayerData
public object competitive_rank { get; set; }
public MmrEstimate mmr_estimate { get; set; }
public Profile profile { get; set; }
public int? rank_tier { get; set; }
}

public class MmrEstimate
Expand Down
49 changes: 49 additions & 0 deletions DotaLass/API/Outputs/PlayerPeer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Newtonsoft.Json;

namespace DotaLass.API.Outputs
{
public class PlayerPeer
{
[JsonProperty(PropertyName = "account_id")]
public int AccountId { get; set; }

[JsonProperty(PropertyName = "last_played")]
public int LastPlayed { get; set; }

[JsonProperty(PropertyName = "win")]
public int Win { get; set; }

[JsonProperty(PropertyName = "games")]
public int Games { get; set; }

[JsonProperty(PropertyName = "with_win")]
public int WithWin { get; set; }

[JsonProperty(PropertyName = "with_games")]
public int WithGames { get; set; }

[JsonProperty(PropertyName = "against_win")]
public int AgainstWin { get; set; }

[JsonProperty(PropertyName = "against_games")]
public int AgainstGames { get; set; }

[JsonProperty(PropertyName = "with_gpm_sum")]
public int WithGpmSum { get; set; }

[JsonProperty(PropertyName = "with_xpm_sum")]
public int WithXpmSum { get; set; }

[JsonProperty(PropertyName = "personaname")]
public string Personaname { get; set; }

[JsonProperty(PropertyName = "last_login")]
public string LastLogin { get; set; }

[JsonProperty(PropertyName = "avatar")]
public string Avatar { get; set; }

[JsonProperty(PropertyName = "avatarfull")]
public string Avatarfull { get; set; }
}
}
31 changes: 26 additions & 5 deletions DotaLass/API/PlayerDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using DotaLass.API.Enums;

namespace DotaLass.API
{
Expand All @@ -28,7 +29,7 @@ public PlayerDisplay()

private CancellationTokenSource CTSource { get; set; }

public void Update(string playerID)
public void Update(string playerID, List<List<string>> groupsList)
{
Data.Clear();

Expand All @@ -50,8 +51,9 @@ public void Update(string playerID)
recentMatches = OpenDotaAPI.GetPlayerMatches(playerID, 20, Settings.Instance.GetDaysLimit(), Settings.Instance.GetLobbyType());

if (!cancelToken.IsCancellationRequested)
Data.ConsumeData(playerID, playerData, recentMatches);

{
Data.ConsumeData(playerID, playerData, recentMatches, groupsList);
}
}, cancelToken).ContinueWith((t) =>
{
RetrievalCompleted?.Invoke(this, null);
Expand All @@ -76,10 +78,12 @@ public class DisplayData : INotifyPropertyChanged
public string Name { get; private set; }
public string SoloMMR { get; private set; }
public string EstimateMMR { get; private set; }
public RankTier? RankTier { get; private set; }

public float Winrate { get; private set; }
public TimeSpan AverageDuration { get; private set; }
public Match[] RecentMatches { get; private set; }
public float AverageKda { get; private set; }
public float AverageKills { get; private set; }
public float AverageDeaths { get; private set; }
public float AverageAssists { get; private set; }
Expand All @@ -89,32 +93,42 @@ public class DisplayData : INotifyPropertyChanged
public float AverageTowerDamage { get; private set; }
public float AverageHeroHealing { get; private set; }
public float AverageLastHits { get; private set; }
public int PartyId { get; private set; }

public event PropertyChangedEventHandler PropertyChanged;

public void ConsumeData(string id, PlayerData playerData, Match[] recentMatches)
public void ConsumeData(string id, PlayerData playerData, Match[] recentMatches, List<List<string>> groupsList)
{
ID = id;

NotifyUpdateLocal();

UpdateGroups(groupsList);
ConsumePlayerData(playerData);
ConsumeRecentMatches(recentMatches);
}

public void UpdateGroups(List<List<string>> groupsList)
{
PartyId = groupsList.FindIndex(e => e.Contains(ID));
}

private void ConsumePlayerData(PlayerData playerData)
{
if (playerData == null || playerData.profile == null)
{
Name = "Anonymous";
SoloMMR = "X";
EstimateMMR = "X";
RankTier = null;
PartyId = -1;
}
else
{
Name = playerData.profile.personaname;
Name = playerData.profile.personaname + (PartyId == -1 ? String.Empty : $" | group: {PartyId}");
SoloMMR = playerData.solo_competitive_rank ?? "X";
EstimateMMR = playerData.mmr_estimate.estimate.HasValue ? playerData.mmr_estimate.estimate.ToString() : "X";
RankTier = playerData.rank_tier.HasValue ? (RankTier?)playerData.rank_tier.Value : null;
}

NotifyUpdateProfile();
Expand Down Expand Up @@ -164,6 +178,7 @@ private void ConsumeRecentMatches(Match[] recentMatches)
AverageKills = totalKills / recentMatches.Length;
AverageDeaths = totalDeaths / recentMatches.Length;
AverageAssists = totalAssists / recentMatches.Length;
AverageKda = (AverageKills + AverageAssists) / (AverageDeaths == 0 ? 1 : AverageDeaths);
AverageXPM = totalXPM / recentMatches.Length;
AverageGPM = totalGPM / recentMatches.Length;
AverageHeroDamage = totalHeroDamage / recentMatches.Length;
Expand All @@ -182,10 +197,13 @@ public void Clear()
Name = "";
SoloMMR = "";
EstimateMMR = "";
RankTier = null;
PartyId = -1;

Winrate = 0;
AverageDuration = TimeSpan.Zero;
RecentMatches = null;
AverageKda = 0;
AverageKills = 0;
AverageDeaths = 0;
AverageAssists = 0;
Expand All @@ -209,6 +227,8 @@ private void NotifyUpdateProfile()
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(EstimateMMR)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SoloMMR)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(RankTier)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PartyId)));
}

private void NotifyUpdateMatches()
Expand All @@ -219,6 +239,7 @@ private void NotifyUpdateMatches()
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AverageKills)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AverageDeaths)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AverageAssists)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AverageKda)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AverageXPM)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AverageGPM)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AverageHeroDamage)));
Expand Down
65 changes: 65 additions & 0 deletions DotaLass/API/RankTierIcons.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Media.Imaging;
using DotaLass.API.Enums;

namespace DotaLass.API
{
public class RankTierIcons
{
private static Dictionary<int, BitmapImage> _rankTierIcons;
private static Dictionary<int, BitmapImage> RankTiersIcons
{
get
{
if (_rankTierIcons == null)
{
_rankTierIcons = new Dictionary<int, BitmapImage>();

var dir = Directory.GetCurrentDirectory() + "/Resources/Images/RankTierIcons/";

var files = Directory.GetFiles(dir, "*.png", SearchOption.AllDirectories);

foreach (var item in files)
{
var fileName = Path.GetFileNameWithoutExtension(item);

int id;
if (int.TryParse(fileName, out id))
{
_rankTierIcons[id] = new BitmapImage(new Uri(item));
}
}
}

return _rankTierIcons;
}
}

public static BitmapImage GetRankTierIcon(RankTier? rankTier)
{
if (!rankTier.HasValue)
return BlankRankTierIcon;

return RankTiersIcons.TryGetValue((int) rankTier, out var output)
? output
: BlankRankTierIcon;
}

private static BitmapImage _blankRankTierIcon;
public static BitmapImage BlankRankTierIcon
{
get
{
if (_blankRankTierIcon == null)
{
var uriSource = new Uri(@"/Resources/Images/RankTierIcons/Empty.png", UriKind.Relative);
_blankRankTierIcon = new BitmapImage(uriSource);
}

return _blankRankTierIcon;
}
}
}
}
Loading