Skip to content

Commit

Permalink
Merge pull request #38 from Atralupus/feat/leaderboard-controller
Browse files Browse the repository at this point in the history
Implement leaderboard controller
  • Loading branch information
Atralupus authored Dec 26, 2024
2 parents 193163d + f266fbc commit 286585a
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 10 deletions.
48 changes: 48 additions & 0 deletions ArenaService.Tests/Controllers/LeaderboardControllerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using ArenaService.Controllers;
using ArenaService.Dtos;
using ArenaService.Models;
using ArenaService.Repositories;
using Microsoft.AspNetCore.Http.HttpResults;
using Moq;

namespace ArenaService.Tests.Controllers;

public class LeaderboardControllerTests
{
private readonly LeaderboardController _controller;
private Mock<ILeaderboardRepository> _leaderboardRepositoryMock;

public LeaderboardControllerTests()
{
var leaderboardRepositoryMock = new Mock<ILeaderboardRepository>();
_leaderboardRepositoryMock = leaderboardRepositoryMock;
_controller = new LeaderboardController(_leaderboardRepositoryMock.Object);
}

[Fact]
public async Task Join_ActivatedSeasonsExist_ReturnsOk()
{
_leaderboardRepositoryMock
.Setup(repo => repo.GetMyRankAsync(1, 1))
.ReturnsAsync(
new LeaderboardEntry
{
Id = 1,
ParticipantId = 1,
Participant = new Participant
{
AvatarAddress = "test",
NameWithHash = "test",
PortraitId = 1
},
Rank = 1,
SeasonId = 1,
TotalScore = 1000
}
);

var result = await _controller.GetMyRank(1, 1);

var okResult = Assert.IsType<Ok<LeaderboardEntryResponse>>(result.Result);
}
}
45 changes: 45 additions & 0 deletions ArenaService/Controllers/LeaderboardController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace ArenaService.Controllers;

using ArenaService.Dtos;
using ArenaService.Extensions;
using ArenaService.Repositories;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;

[Route("seasons/{seasonId}/leaderboard")]
[ApiController]
public class LeaderboardController : ControllerBase
{
private readonly ILeaderboardRepository _leaderboardRepository;

public LeaderboardController(ILeaderboardRepository leaderboardRepository)
{
_leaderboardRepository = leaderboardRepository;
}

// [HttpGet]
// public async Task<Results<NotFound<string>, Ok<AvailableOpponentsResponse>>> GetLeaderboard(
// int seasonId,
// int offset,
// int limit
// )
// {
// var leaderboard = await _leaderboardRepository.GetLeaderboard(seasonId, offset, limit);
// }

[HttpGet("participants/{participantId}")]
public async Task<Results<NotFound<string>, Ok<LeaderboardEntryResponse>>> GetMyRank(
int seasonId,
int participantId
)
{
var leaderboardEntry = await _leaderboardRepository.GetMyRankAsync(seasonId, participantId);

if (leaderboardEntry == null)
{
return TypedResults.NotFound("No leaderboardEntry found.");
}

return TypedResults.Ok(leaderboardEntry.ToResponse());
}
}
10 changes: 10 additions & 0 deletions ArenaService/Dtos/LeaderboardEntryResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace ArenaService.Dtos;

public class LeaderboardEntryResponse
{
public required string AvatarAddress { get; set; }
public required string NameWithHash { get; set; }
public int PortraitId { get; set; }
public int Rank { get; set; }
public int TotalScore { get; set; }
}
24 changes: 24 additions & 0 deletions ArenaService/Extensions/LeaderboardExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace ArenaService.Extensions;

using ArenaService.Dtos;
using ArenaService.Models;

public static class LeaderboardExtensions
{
public static LeaderboardEntryResponse ToResponse(this LeaderboardEntry leaderboardEntry)
{
return new LeaderboardEntryResponse
{
AvatarAddress = leaderboardEntry.Participant.AvatarAddress,
NameWithHash = leaderboardEntry.Participant.NameWithHash,
PortraitId = leaderboardEntry.Participant.PortraitId,
Rank = leaderboardEntry.Rank,
TotalScore = leaderboardEntry.TotalScore
};
}

public static List<LeaderboardEntryResponse> ToResponse(this List<LeaderboardEntry> leaderboard)
{
return leaderboard.Select(lbe => lbe.ToResponse()).ToList();
}
}
9 changes: 1 addition & 8 deletions ArenaService/Extensions/ParticipantExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ public static ParticipantResponse ToResponse(this Participant participant)

public static List<ParticipantResponse> ToResponse(this List<Participant> participants)
{
return participants
.Select(p => new ParticipantResponse
{
AvatarAddress = p.AvatarAddress,
NameWithHash = p.NameWithHash,
PortraitId = p.PortraitId,
})
.ToList();
return participants.Select(p => p.ToResponse()).ToList();
}
}
4 changes: 2 additions & 2 deletions ArenaService/Models/LeaderboardEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ public class LeaderboardEntry

[Required]
public int ParticipantId { get; set; }
public required Participant Participant { get; set; }
public Participant Participant { get; set; } = null!;

[Required]
public int SeasonId { get; set; }
public required Season Season { get; set; }
public Season Season { get; set; } = null!;

[Required]
public int Rank { get; set; }
Expand Down
43 changes: 43 additions & 0 deletions ArenaService/Repositories/LeaderboardRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace ArenaService.Repositories;

using ArenaService.Data;
using ArenaService.Models;
using Microsoft.EntityFrameworkCore;

public interface ILeaderboardRepository
{
// Task<List<LeaderboardEntry>> GetLeaderboard(int seasonId, int offset, int limit);
Task<LeaderboardEntry?> GetMyRankAsync(int seasonId, int participantId);
}

public class LeaderboardRepository : ILeaderboardRepository
{
private readonly ArenaDbContext _context;

public LeaderboardRepository(ArenaDbContext context)
{
_context = context;
}

// public async Task<Participant> GetLeaderboard(
// int seasonId,
// string avatarAddress,
// string nameWithHash,
// int portraitId
// )
// {
// var nextPage = context
// .Leaderboard.OrderBy(b => b.Date)
// .ThenBy(b => b.PostId)
// .Where(b => b.Date > lastDate || (b.Date == lastDate && b.PostId > lastId))
// .Take(10)
// .ToList();
// }

public async Task<LeaderboardEntry?> GetMyRankAsync(int seasonId, int participantId)
{
return await _context.Leaderboard.FirstOrDefaultAsync(lb =>
lb.SeasonId == seasonId && lb.ParticipantId == participantId
);
}
}

0 comments on commit 286585a

Please sign in to comment.