diff --git a/LaDOSE.Src/LaDOSE.Api/Controllers/SmashController.cs b/LaDOSE.Src/LaDOSE.Api/Controllers/SmashController.cs new file mode 100644 index 0000000..a4f34b1 --- /dev/null +++ b/LaDOSE.Src/LaDOSE.Api/Controllers/SmashController.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using AutoMapper; +using LaDOSE.Business.Interface; +using LaDOSE.DTO; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace LaDOSE.Api.Controllers +{ +#if DEBUG + [AllowAnonymous] +#endif + [Produces("application/json")] + [Route("api/[controller]")] + public class SmashController : Controller + { + + private ITournamentService _service; + + private IMapper _mapper; + + // GET + public SmashController(IMapper mapper, ITournamentService service) + { + _mapper = mapper; + _service = service; + } + //This may be a get , but i dont know what the RFC State for Get request with Body + //As i don't like to populate GET request with body this will be a post (and i think + //it will be easier to proxy. + [HttpGet("GetTournament/{tournamentSlug}")] + public async Task GetSmashTournament(string tournamentSlug) + { + if (!String.IsNullOrEmpty(tournamentSlug)) + { + var tournaments = await _service.GetSmashResult(tournamentSlug); + + return Ok(tournaments); + } + + return null; + } + + //[HttpPost("GetResults")] + //public async Task GetResults([FromBody] List ids) + //{ + // if (ids == null) + // { + // throw new Exception("Invalid arguments"); + // } + + // var tournamentsResult = await _service.GetTournamentsResult(ids); + // return _mapper.Map(tournamentsResult); + + //} + + + } +} diff --git a/LaDOSE.Src/LaDOSE.Api/Controllers/TournamentController.cs b/LaDOSE.Src/LaDOSE.Api/Controllers/TournamentController.cs index 8d08b86..2d98c1b 100644 --- a/LaDOSE.Src/LaDOSE.Api/Controllers/TournamentController.cs +++ b/LaDOSE.Src/LaDOSE.Api/Controllers/TournamentController.cs @@ -36,12 +36,10 @@ namespace LaDOSE.Api.Controllers var tournaments = await _service.GetTournaments(dto.From, dto.To); return _mapper.Map>(tournaments); } - - + return null; } - [HttpPost("GetResults")] public async Task GetResults([FromBody] List ids) { @@ -54,5 +52,7 @@ namespace LaDOSE.Api.Controllers return _mapper.Map(tournamentsResult); } + + } } \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Api/Startup.cs b/LaDOSE.Src/LaDOSE.Api/Startup.cs index be962ab..6b6cd94 100644 --- a/LaDOSE.Src/LaDOSE.Api/Startup.cs +++ b/LaDOSE.Src/LaDOSE.Api/Startup.cs @@ -26,6 +26,8 @@ using Pomelo.EntityFrameworkCore.MySql.Infrastructure; using AutoMapper; using LaDOSE.Api.Helpers; using LaDOSE.Business.Helper; +using LaDOSE.Business.Provider.ChallongProvider; +using LaDOSE.Business.Provider.SmashProvider; using LaDOSE.Entity.Challonge; using LaDOSE.Entity.Wordpress; @@ -140,6 +142,7 @@ namespace LaDOSE.Api { services.AddTransient(p => new ChallongeProvider(this.Configuration["ApiKey:ChallongeApiKey"])); + services.AddTransient(p => new SmashProvider(this.Configuration["ApiKey:SmashApiKey"])); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/LaDOSE.Src/LaDOSE.DesktopApp/ViewModels/TournamentResultViewModel.cs b/LaDOSE.Src/LaDOSE.DesktopApp/ViewModels/TournamentResultViewModel.cs index 071e897..1586133 100644 --- a/LaDOSE.Src/LaDOSE.DesktopApp/ViewModels/TournamentResultViewModel.cs +++ b/LaDOSE.Src/LaDOSE.DesktopApp/ViewModels/TournamentResultViewModel.cs @@ -44,6 +44,17 @@ namespace LaDOSE.DesktopApp.ViewModels } } + private string _slug; + public String Slug + { + get { return _slug; } + set + { + _slug = value; + NotifyOfPropertyChange(() => Slug); + } + } + private String _html; public String Html @@ -213,7 +224,17 @@ namespace LaDOSE.DesktopApp.ViewModels ComputeHtml(); }); } - + public void GetSmash() + { + WpfUtil.Await(() => + { + + var resultsDto = this.RestService.GetSmashResults(Slug); + this.Results = resultsDto; + ComputeDataGrid(); + ComputeHtml(); + }); + } public void SelectYear() { @@ -318,7 +339,7 @@ namespace LaDOSE.DesktopApp.ViewModels { StringBuilder sb = new StringBuilder(); - sb.Append(""); + sb.Append("
"); int columns = 0; foreach (var game in Results.Games) @@ -329,14 +350,19 @@ namespace LaDOSE.DesktopApp.ViewModels sb.Append(""); } columns++; - sb.Append(""); + if (top3.Count >= 3) + { + sb.AppendLine($"
1/ {top3[0]}
2/ {top3[1]}
3/ {top3[2]}
"); + sb.AppendLine($"https://challonge.com/fr/{enumerable.First().TournamentUrl}

"); + } + + if (columns % 2 == 0) { sb.Append(""); diff --git a/LaDOSE.Src/LaDOSE.DesktopApp/Views/TournamentResultView.xaml b/LaDOSE.Src/LaDOSE.DesktopApp/Views/TournamentResultView.xaml index a795d3d..05d3896 100644 --- a/LaDOSE.Src/LaDOSE.DesktopApp/Views/TournamentResultView.xaml +++ b/LaDOSE.Src/LaDOSE.DesktopApp/Views/TournamentResultView.xaml @@ -18,6 +18,7 @@ + @@ -84,6 +85,7 @@ + @@ -171,7 +173,12 @@ + - + + Slug : + + + \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Entity/Game.cs b/LaDOSE.Src/LaDOSE.Entity/Game.cs index 287d231..dc4735f 100644 --- a/LaDOSE.Src/LaDOSE.Entity/Game.cs +++ b/LaDOSE.Src/LaDOSE.Entity/Game.cs @@ -11,8 +11,18 @@ namespace LaDOSE.Entity public int Order { get; set; } public string WordPressTag { get; set; } public string WordPressTagOs { get; set; } + + public int? SmashId { get; set; } public virtual IEnumerable Seasons { get; set; } public virtual IEnumerable Events { get; set; } + } + public class SmashParticipent : Context.Entity + { + public string Name { get; set; } + public string Tag { get; set; } + public int? SmashId{ get; set; } + + } } diff --git a/LaDOSE.Src/LaDOSE.REST/RestService.cs b/LaDOSE.Src/LaDOSE.REST/RestService.cs index b225f19..5565c7a 100644 --- a/LaDOSE.Src/LaDOSE.REST/RestService.cs +++ b/LaDOSE.Src/LaDOSE.REST/RestService.cs @@ -267,6 +267,14 @@ namespace LaDOSE.REST } + public TournamentsResultDTO GetSmashResults(string slug) + { + CheckToken(); + var restRequest = new RestRequest($"Api/Smash/GetTournament/{slug}", Method.GET); + var restResponse = Client.Get(restRequest); + return restResponse.Data; + + } #endregion } diff --git a/LaDOSE.Src/LaDOSE.Service/Helper/DistinctBy.cs b/LaDOSE.Src/LaDOSE.Service/Helper/DistinctBy.cs new file mode 100644 index 0000000..8f3d4ad --- /dev/null +++ b/LaDOSE.Src/LaDOSE.Service/Helper/DistinctBy.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LaDOSE.Business.Helper +{ + public static class DataHelper + { + public static IEnumerable DistinctBy(this IEnumerable lst,Func dist) + { + var seen = new HashSet(); + foreach (var e in lst) + { + + if (!seen.Contains(dist(e))) + { + seen.Add(dist(e)); + yield return e; + } + } + } + } +} \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Service/Interface/IChallongeProvider.cs b/LaDOSE.Src/LaDOSE.Service/Interface/IChallongeProvider.cs index 02a67a1..507e8ed 100644 --- a/LaDOSE.Src/LaDOSE.Service/Interface/IChallongeProvider.cs +++ b/LaDOSE.Src/LaDOSE.Service/Interface/IChallongeProvider.cs @@ -18,4 +18,5 @@ namespace LaDOSE.Business.Interface Task GetTournament(int idTournament); Task GetTournament(string urlTournament); } + } \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Service/Interface/ISmashProvider.cs b/LaDOSE.Src/LaDOSE.Service/Interface/ISmashProvider.cs new file mode 100644 index 0000000..97512ca --- /dev/null +++ b/LaDOSE.Src/LaDOSE.Service/Interface/ISmashProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LaDOSE.Business.Provider.SmashProvider; +using LaDOSE.Entity.Challonge; + +namespace LaDOSE.Business.Interface +{ + public interface ISmashProvider + { + Task> GetTournaments(DateTime? start, DateTime? end); + Task GetTournament(string sludge); + + } +} \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Service/Interface/ITournamentService.cs b/LaDOSE.Src/LaDOSE.Service/Interface/ITournamentService.cs index 0f34f9c..04843a6 100644 --- a/LaDOSE.Src/LaDOSE.Service/Interface/ITournamentService.cs +++ b/LaDOSE.Src/LaDOSE.Service/Interface/ITournamentService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using LaDOSE.Business.Provider.SmashProvider; using LaDOSE.Entity.Challonge; namespace LaDOSE.Business.Interface @@ -10,5 +11,6 @@ namespace LaDOSE.Business.Interface Task> GetTournaments(DateTime? start, DateTime? end); Task GetTournamentsResult(List ids); + Task GetSmashResult(string tournamentSlug); } } \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Service/LaDOSE.Business.csproj b/LaDOSE.Src/LaDOSE.Service/LaDOSE.Business.csproj index 21919f3..756e717 100644 --- a/LaDOSE.Src/LaDOSE.Service/LaDOSE.Business.csproj +++ b/LaDOSE.Src/LaDOSE.Service/LaDOSE.Business.csproj @@ -7,6 +7,11 @@ AnyCPU;x64 + + + + + diff --git a/LaDOSE.Src/LaDOSE.Service/Provider/ChallongeProvider.cs b/LaDOSE.Src/LaDOSE.Service/Provider/ChallongProvider/ChallongeProvider.cs similarity index 92% rename from LaDOSE.Src/LaDOSE.Service/Provider/ChallongeProvider.cs rename to LaDOSE.Src/LaDOSE.Service/Provider/ChallongProvider/ChallongeProvider.cs index f70c76f..238b8b2 100644 --- a/LaDOSE.Src/LaDOSE.Service/Provider/ChallongeProvider.cs +++ b/LaDOSE.Src/LaDOSE.Service/Provider/ChallongProvider/ChallongeProvider.cs @@ -10,7 +10,7 @@ using ChallongeCSharpDriver.Core.Results; using LaDOSE.Business.Interface; using LaDOSE.Entity.Challonge; -namespace LaDOSE.Business.Provider +namespace LaDOSE.Business.Provider.ChallongProvider { public class ChallongeProvider : IChallongeProvider { @@ -30,9 +30,9 @@ namespace LaDOSE.Business.Provider DernierTournois = "Aucun tournois."; } - public async Task CreateTournament(string name, string url,DateTime? startAt = null) + public async Task CreateTournament(string name, string url, DateTime? startAt = null) { - var result = await new CreateTournamentQuery(name, startAt , TournamentType.Double_Elimination, url).call(ApiCaller); + var result = await new CreateTournamentQuery(name, startAt, TournamentType.Double_Elimination, url).call(ApiCaller); return result; @@ -50,13 +50,13 @@ namespace LaDOSE.Business.Provider { List tournamentResultList = await new TournamentsQuery() - { - state = TournamentState.Ended, - createdAfter = start, - createdBefore = DateTime.Now, + { + state = TournamentState.Ended, + createdAfter = start, + createdBefore = DateTime.Now, - } + } .call(this.ApiCaller); List tournaments = new List(); tournamentResultList.ForEach(w => tournaments.Add(new ChallongeTournament() @@ -70,7 +70,7 @@ namespace LaDOSE.Business.Provider public async Task> GetParticipents(int idTournament) { - var participentResults = await new ParticipantsQuery(){tournamentID = idTournament }.call(ApiCaller); + var participentResults = await new ParticipantsQuery() { tournamentID = idTournament }.call(ApiCaller); List participants = new List(); participentResults.ForEach(w => @@ -86,7 +86,7 @@ namespace LaDOSE.Business.Provider IsMember = false, }); } - + }); return participants; } @@ -102,7 +102,7 @@ namespace LaDOSE.Business.Provider Name = tournamentResult.name, Url = tournamentResult.url, Participents = new List() - + }; } @@ -136,7 +136,7 @@ namespace LaDOSE.Business.Provider var lastDate = tournamentResultList.Max(e => e.completed_at); - + if (lastDate.HasValue) { var lastRankingDate = new DateTime(lastDate.Value.Year, lastDate.Value.Month, lastDate.Value.Day); diff --git a/LaDOSE.Src/LaDOSE.Service/Provider/SmashProvider/SmashProvider.cs b/LaDOSE.Src/LaDOSE.Service/Provider/SmashProvider/SmashProvider.cs new file mode 100644 index 0000000..89672b2 --- /dev/null +++ b/LaDOSE.Src/LaDOSE.Service/Provider/SmashProvider/SmashProvider.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using GraphQL; +using GraphQL.Client.Http; +using GraphQL.Client.Serializer.Newtonsoft; +using LaDOSE.Business.Interface; +using LaDOSE.Entity.Challonge; + +namespace LaDOSE.Business.Provider.SmashProvider +{ + public class SmashProvider : ISmashProvider + { + public string ApiKey { get; set; } + public SmashProvider(string apiKey) + { + this.ApiKey = apiKey; + } + + public Task> GetTournaments(DateTime? start, DateTime? end) + { + var list = new List(); + var personAndFilmsRequest = new GraphQLRequest + { + Query = @" + query TournamentsByOwner($perPage: Int!, $ownerId: ID!) { + tournaments(query: { + perPage: $perPage + filter: { + ownerId: $ownerId + } + }) { + nodes { + id + name + slug + } + } + }", + + OperationName = "PersonAndFilms", + Variables = new + { + + ownerId = "161429", + perPage = "4" + + } + }; + + + return Task.FromResult(list); + } + + public async Task GetTournament(string slug) + { + var graphQLClient = new GraphQLHttpClient("https://api.smash.gg/gql/alpha", new NewtonsoftJsonSerializer()); + graphQLClient.HttpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}"); + var Event = new GraphQLRequest + { + Query = @"query TournamentQuery($slug: String) { + tournament(slug: $slug){ + id + name + events { + id + name, + state, + videogame { + id, + name, + displayName + } + standings(query: {page:0,perPage:500}){ + nodes{ + id, + player{ + id, + gamerTag, + user { + id, + name, + player { + id + } + } + } + placement + } + + } + } + + } + }", + OperationName = "TournamentQuery", + Variables = new + { + slug = slug, + } + }; + + //GraphQLHttpRequest preprocessedRequest = await graphQLClient.Options.PreprocessRequest(Event, graphQLClient); + //var x = preprocessedRequest.ToHttpRequestMessage(graphQLClient.Options, new NewtonsoftJsonSerializer()); + //System.Diagnostics.Trace.WriteLine(x.Content.ReadAsStringAsync().Result); + //var sendAsync = await graphQLClient.HttpClient.SendAsync(x); + //System.Diagnostics.Trace.WriteLine(sendAsync.Content.ReadAsStringAsync().Result); + + var graphQLResponse = await graphQLClient.SendQueryAsync(Event); + if (graphQLResponse.Errors != null) + { + //Event not done ? + //throw new Exception("Error"); + } + System.Diagnostics.Trace.Write(graphQLResponse.Data.Tournament.Name); + + return graphQLResponse.Data; + } + } +} \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Service/Provider/SmashProvider/Tournament.cs b/LaDOSE.Src/LaDOSE.Service/Provider/SmashProvider/Tournament.cs new file mode 100644 index 0000000..c1a30da --- /dev/null +++ b/LaDOSE.Src/LaDOSE.Service/Provider/SmashProvider/Tournament.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; + +namespace LaDOSE.Business.Provider.SmashProvider +{ + public class ResponseType + { + public TournamentType Tournament { get; set; } + public class TournamentType + { + public int id { get; set; } + + public string Name { get; set; } + + public List Events { get; set; } + + } + + public class Event + { + public int id { get; set; } + + public string name { get; set; } + public string state { get; set; } + + public VideoGame videogame { get; set; } + public Node standings { get; set; } + } + + public class VideoGame + { + public int id { get; set; } + public string Name { get; set; } + } + + public class Node + { + public List nodes { get; set; } + + } + public class Standing + { + public int id { get; set; } + + public int placement { get; set; } + + public Player player { get; set; } + } + public class Player + { + public int id { get; set; } + public string gamerTag { get; set; } + public User user { get; set; } + } + public class User + { + public int id { get; set; } + public string name { get; set; } + + } + + } + + + + +} \ No newline at end of file diff --git a/LaDOSE.Src/LaDOSE.Service/Service/TournamentService.cs b/LaDOSE.Src/LaDOSE.Service/Service/TournamentService.cs index c8dd54e..f61fa97 100644 --- a/LaDOSE.Src/LaDOSE.Service/Service/TournamentService.cs +++ b/LaDOSE.Src/LaDOSE.Service/Service/TournamentService.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using LaDOSE.Business.Helper; using LaDOSE.Business.Interface; +using LaDOSE.Business.Provider.SmashProvider; using LaDOSE.Entity; using LaDOSE.Entity.Challonge; using LaDOSE.Entity.Context; @@ -50,12 +52,16 @@ namespace LaDOSE.Business.Service new Rules(16, 32, 12, 8, 5, 3, 2), new Rules(32, Int32.MaxValue, 18, 12, 8, 5, 3), }; + + private ISmashProvider _smashProvider; + #endregion - public TournamentService(LaDOSEDbContext context, IChallongeProvider challongeProvider) : base(context) + public TournamentService(LaDOSEDbContext context, IChallongeProvider challongeProvider, ISmashProvider _smashProvider) : base(context) { this._context = context; this._challongeProvider = challongeProvider; + this._smashProvider = _smashProvider; } public async Task> GetTournaments(DateTime? start, DateTime? end) @@ -147,6 +153,89 @@ namespace LaDOSE.Business.Service return result; } + public async Task GetSmashResult(string tournamentSlug) + { + var tournaments = await _smashProvider.GetTournament(tournamentSlug); + var players = tournaments.Tournament.Events.Where(e=>e.standings != null ).SelectMany(e => e.standings.nodes.Select(e => e.player)).ToList(); + var distinctp = players.DistinctBy(e=>new {e.user.id}).ToList(); + var games = _context.Game.ToList(); + + TournamentsResult result = new TournamentsResult(); + result.Results = new List(); + result.Games = new List(); + result.Participents = new List(); + distinctp.ForEach(e => + { + var x = new ChallongeParticipent() + { + Name = e.gamerTag, + ChallongeId = e.id, + Id = e.id + }; + result.Participents.Add(x); + }); + games.ForEach(e => + { + e.Id = e.SmashId ?? e.Id; + result.Games.Add(e); + }); + + foreach (var tournament in tournaments.Tournament.Events.Where(e=>e.standings!=null).ToList()) + { + + + var playerCount = tournament.standings.nodes.Count; + var lesSacs = tournament.standings.nodes; + var currentRule = TournamentRules.FirstOrDefault(rules => + rules.PlayerMin < playerCount && rules.PlayerMax >= playerCount + ); + if (currentRule == null) + { + throw new Exception("Unable to find rules"); + } + + var first = tournament.standings.nodes.First(p => p.placement == 1); + var second = tournament.standings.nodes.First(p => p.placement == 2); + var thirdFourth = tournament.standings.nodes.Where(p => p.placement == 3 || p.placement == 4).ToList(); + var Top8 = tournament.standings.nodes.Where(p => p.placement > 4 && p.placement < 9).ToList(); + var Top16 = tournament.standings.nodes.Where(p => p.placement > 8 && p.placement <= 16).ToList(); + + result.Results.Add(new Result(first.player.gamerTag, tournament.videogame.id, tournament.id, tournament.name, currentRule.FirstPoint, first.placement)); + lesSacs.Remove(first); + result.Results.Add(new Result(second.player.gamerTag, tournament.videogame.id, tournament.id, tournament.name, currentRule.SecondPoint, second.placement)); + lesSacs.Remove(second); + thirdFourth.ForEach(r => + result.Results.Add(new Result(r.player.gamerTag, tournament.videogame.id, tournament.id, tournament.name, + currentRule.ThirdFourthPoint, r.placement))); + thirdFourth.ForEach(p => lesSacs.Remove(p)); + if (currentRule.Top8Point != 0) + { + Top8.ForEach(r => + result.Results.Add(new Result(r.player.gamerTag, tournament.videogame.id, tournament.id, tournament.name, + currentRule.ThirdFourthPoint, r.placement))); + Top8.ForEach(p => lesSacs.Remove(p)); + } + + if (currentRule.Top16Point != 0) + { + Top16.ForEach(r => + result.Results.Add( + new Result(r.player.gamerTag, tournament.videogame.id, tournament.id, tournament.name, + currentRule.ThirdFourthPoint, r.placement))); + Top16.ForEach(p => lesSacs.Remove(p)); + } + + lesSacs.ForEach(r => + result.Results.Add(new Result(r.player.gamerTag, tournament.videogame.id, tournament.id, tournament.name, + currentRule.ThirdFourthPoint, r.placement))); + + } + + + + return await Task.FromResult(result); + } + /// /// Check if the tournament exist in database otherwise call Challonge. ///
" + + sb.Append("" + "" + $"{game.LongName} ({Results.Results.Count(e => e.GameId == game.Id)} participants) :" + ""); List enumerable = Results.Results.Where(r => r.GameId == game.Id).ToList(); List top3 = enumerable.OrderBy(e => e.Rank).Take(3).Select(e => e.Player).ToList(); - sb.AppendLine($"
1/ {top3[0]}
2/ {top3[1]}
3/ {top3[2]}

"); - sb.AppendLine($"https://challonge.com/fr/{enumerable.First().TournamentUrl}