Skip to content
Merged
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
5 changes: 4 additions & 1 deletion WheelWizard.Test/Features/WhWzDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,10 @@ public async Task LoadBadgesAsync_OverwritesExistingBadges_WhenCalledMultipleTim
Assert.Contains(BadgeVariant.WhWzDev, initialBadges);

// Arrange - Second load with different data
var updatedBadgeData = new Dictionary<string, BadgeVariant[]> { { "FC1", [BadgeVariant.Translator, BadgeVariant.Firestarter_GoldWinner] } };
var updatedBadgeData = new Dictionary<string, BadgeVariant[]>
{
{ "FC1", [BadgeVariant.Translator, BadgeVariant.Firestarter_GoldWinner] },
};

_apiCaller
.CallApiAsync(Arg.Any<Expression<Func<IWhWzDataApi, Task<Dictionary<string, BadgeVariant[]>>>>>())
Expand Down
7 changes: 5 additions & 2 deletions WheelWizard/Features/RrRooms/Domain/IRwfcApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ namespace WheelWizard.RrRooms;

public interface IRwfcApi
{
[Get("/api/groups")]
Task<List<RwfcRoom>> GetWiiGroupsAsync();
[Get("/api/roomstatus")]
Task<RwfcRoomStatusResponse> GetRoomStatusAsync();

[Get("/api/leaderboard/top/{limit}")]
Task<List<RwfcLeaderboardEntry>> GetTopLeaderboardAsync(int limit);
}
20 changes: 20 additions & 0 deletions WheelWizard/Features/RrRooms/Domain/RwfcLeaderboardEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace WheelWizard.RrRooms;

public sealed class RwfcLeaderboardEntry
{
public required string Pid { get; set; }
public string Name { get; set; } = string.Empty;
public string FriendCode { get; set; } = string.Empty;

public int? Vr { get; set; }
public int? Rank { get; set; }
public int? ActiveRank { get; set; }

public DateTime? LastSeen { get; set; }
public bool IsActive { get; set; }
public bool IsSuspicious { get; set; }

public RwfcLeaderboardVrStats? VrStats { get; set; }

public string? MiiImageBase64 { get; set; }
}
8 changes: 8 additions & 0 deletions WheelWizard/Features/RrRooms/Domain/RwfcLeaderboardVrStats.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace WheelWizard.RrRooms;

public sealed class RwfcLeaderboardVrStats
{
public int Last24Hours { get; set; } = 0;
public int LastWeek { get; set; } = 0;
public int LastMonth { get; set; } = 0;
}
15 changes: 0 additions & 15 deletions WheelWizard/Features/RrRooms/Domain/RwfcPlayer.cs

This file was deleted.

19 changes: 19 additions & 0 deletions WheelWizard/Features/RrRooms/Domain/RwfcRoomStatusPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace WheelWizard.RrRooms;

public sealed class RwfcRoomStatusPlayer
{
public required string Pid { get; set; }
public string Name { get; set; } = string.Empty;

public string FriendCode { get; set; } = string.Empty;

public int? Vr { get; set; }
public int? Br { get; set; }

public bool IsOpenHost { get; set; }
public bool IsSuspended { get; set; }

public RwfcMii? Mii { get; set; }

public List<string> ConnectionMap { get; set; } = [];
}
13 changes: 13 additions & 0 deletions WheelWizard/Features/RrRooms/Domain/RwfcRoomStatusResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace WheelWizard.RrRooms;

public sealed class RwfcRoomStatusResponse
{
public required List<RwfcRoomStatusRoom> Rooms { get; set; }

//todo: figure out what these refer to:
public DateTime Timestamp { get; set; }

public int? Id { get; set; }
public int? MinimumId { get; set; }
public int? MaximumId { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
namespace WheelWizard.RrRooms;

public sealed class RwfcRoom
public sealed class RwfcRoomStatusRoom
{
public required string Id { get; set; }

public string? Game { get; set; }
public required DateTime Created { get; set; }
public required string Type { get; set; }
public required bool Suspend { get; set; }
public required DateTime Created { get; set; }

public string? Host { get; set; }
public string? Rk { get; set; }
public required Dictionary<string, RwfcPlayer> Players { get; set; }

public required List<RwfcRoomStatusPlayer> Players { get; set; }

public bool Suspend { get; set; }
}
17 changes: 17 additions & 0 deletions WheelWizard/Features/RrRooms/RrLeaderboardSingletonService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using WheelWizard.Shared.Services;

namespace WheelWizard.RrRooms;

public interface IRrLeaderboardSingletonService
{
Task<OperationResult<List<RwfcLeaderboardEntry>>> GetTopPlayersAsync(int limit = 50);
}

public class RrLeaderboardSingletonService(IApiCaller<IRwfcApi> apiCaller) : IRrLeaderboardSingletonService
{
public async Task<OperationResult<List<RwfcLeaderboardEntry>>> GetTopPlayersAsync(int limit = 50)
{
var boundedLimit = Math.Clamp(limit, 1, 200);
return await apiCaller.CallApiAsync(api => api.GetTopLeaderboardAsync(boundedLimit));
}
}
6 changes: 5 additions & 1 deletion WheelWizard/Features/RrRooms/RrRoomsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ public static class RrRoomsExtensions
{
public static IServiceCollection AddRrRooms(this IServiceCollection services)
{
services.AddWhWzRefitApi<IRwfcApi>(Endpoints.RwfcBaseAddress, new() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower });
services.AddWhWzRefitApi<IRwfcApi>(
Endpoints.RwfcBaseAddress,
new() { PropertyNameCaseInsensitive = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
);

services.AddSingleton<IRrRoomsSingletonService, RrRoomsSingletonService>();
services.AddSingleton<IRrLeaderboardSingletonService, RrLeaderboardSingletonService>();

return services;
}
Expand Down
10 changes: 7 additions & 3 deletions WheelWizard/Features/RrRooms/RrRoomsSingletonService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ namespace WheelWizard.RrRooms;

public interface IRrRoomsSingletonService
{
Task<OperationResult<List<RwfcRoom>>> GetRoomsAsync();
Task<OperationResult<List<RwfcRoomStatusRoom>>> GetRoomsAsync();
}

public class RrRoomsSingletonService(IApiCaller<IRwfcApi> apiCaller) : IRrRoomsSingletonService
{
public async Task<OperationResult<List<RwfcRoom>>> GetRoomsAsync()
public async Task<OperationResult<List<RwfcRoomStatusRoom>>> GetRoomsAsync()
{
return await apiCaller.CallApiAsync(rwfcApi => rwfcApi.GetWiiGroupsAsync());
var result = await apiCaller.CallApiAsync(rwfcApi => rwfcApi.GetRoomStatusAsync());
if (result.IsFailure)
return result.Error;

return result.Value.Rooms;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public bool IsOnline
if (currentRooms.Count <= 0)
return false;

var onlinePlayers = currentRooms.SelectMany(room => room.Players.Values).ToList();
return onlinePlayers.Any(player => player.Fc == FriendCode);
var onlinePlayers = currentRooms.SelectMany(room => room.Players).ToList();
return onlinePlayers.Any(player => player.FriendCode == FriendCode);
}
set
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ public GameLicenseSingletonService(IMiiDbService miiService, IFileSystem fileSys
public void RefreshOnlineStatus()
{
var currentRooms = RRLiveRooms.Instance.CurrentRooms;
var onlinePlayers = currentRooms.SelectMany(room => room.Players.Values).ToList();
var onlinePlayers = currentRooms.SelectMany(room => room.Players).ToList();
foreach (var user in Licenses.Users)
{
user.IsOnline = onlinePlayers.Any(player => player.Fc == user.FriendCode);
user.IsOnline = onlinePlayers.Any(player => player.FriendCode == user.FriendCode);
}
}

Expand Down
44 changes: 31 additions & 13 deletions WheelWizard/Models/RRInfo/RrPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,43 @@

namespace WheelWizard.Models.RRInfo;

public class RrPlayer
public class RrPlayer : IEquatable<RrPlayer>
{
// These variables should not be renamed since they are directly mapped to the JSON object
public required string Count { get; set; } // you can have one Wii that with 2 players (and hence the Mii list)
public required string Pid { get; set; }
public required string Name { get; set; }
public required string ConnMap { get; set; } // its always there, but we dont use
public required string ConnFail { get; set; }
public required string Suspend { get; set; }
public required string Fc { get; set; }
public string Ev { get; set; } = "--"; // private games don't have EV and EB
public string Eb { get; set; } = "--";
public List<Mii> Mii { get; set; } = [];
public required string FriendCode { get; set; }

public int PlayerCount => int.Parse(Count);
public Mii? FirstMii => Mii.Count <= 0 ? null : Mii[0];
public int? Vr { get; set; }
public int? Br { get; set; }

public int Vr => int.TryParse(Ev, out var evValue) ? evValue : -1;
public bool IsOpenHost { get; set; }
public bool IsSuspended { get; set; }

public int? LeaderboardRank { get; set; }
public bool IsTopLeaderboardPlayer => LeaderboardRank.HasValue;
public string TopLabel => LeaderboardRank is { } rank ? $"#{rank}" : string.Empty;

public List<string> ConnectionMap { get; set; } = [];

public Mii? Mii { get; set; }

public Mii? FirstMii => Mii;

public string VrDisplay => Vr?.ToString() ?? "--";
public string BrDisplay => Br?.ToString() ?? "--";

public BadgeVariant[] BadgeVariants { get; set; } = [];
public bool HasBadges => BadgeVariants.Length != 0;

public bool Equals(RrPlayer? other)
{
if (other is null)
return false;
return string.Equals(Pid, other.Pid, StringComparison.Ordinal)
&& string.Equals(FriendCode, other.FriendCode, StringComparison.Ordinal);
}

public override bool Equals(object? obj) => obj is RrPlayer other && Equals(other);

public override int GetHashCode() => HashCode.Combine(Pid, FriendCode);
}
19 changes: 13 additions & 6 deletions WheelWizard/Models/RRInfo/RrRoom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ namespace WheelWizard.Models.RRInfo;
public class RrRoom
{
public required string Id { get; set; }
public string? Game { get; set; } // it always exists, but we dont care since we dont use it (and its always "mariokartwii")
public required DateTime Created { get; set; }
public required string Type { get; set; }
public required bool Suspend { get; set; }
public string? Host { get; set; } // the key of player in the players map (that started the room)
public string? Rk { get; set; } // RK does not exists in private rooms
public required Dictionary<string, RrPlayer> Players { get; set; }
public required List<RrPlayer> Players { get; set; }

public int PlayerCount => Players.Sum(p => p.Value.PlayerCount);
public int PlayerCount => Players.Count;

public string TimeOnline => Humanizer.HumanizeTimeSpan(DateTime.UtcNow - Created);
public bool IsPublic => Type != "private";
Expand Down Expand Up @@ -139,7 +137,16 @@ public class RrRoom
_ => IsPublic ? "Unknown Mode" : "Private Room",
};

public int AverageVr => PlayerCount == 0 ? 0 : Players.Sum(p => p.Value.Vr) / PlayerCount;
public int AverageVr
{
get
{
var vrs = Players.Select(p => p.Vr).Where(v => v.HasValue).Select(v => v!.Value).ToList();
return vrs.Count == 0 ? 0 : (int)vrs.Average();
}
}

public RrPlayer? HostPlayer => Players.FirstOrDefault(p => p.IsOpenHost);

public Mii? HostMii => !string.IsNullOrEmpty(Host) ? Players.GetValueOrDefault(Host)?.FirstMii : null;
public Mii? HostMii => HostPlayer?.FirstMii;
}
2 changes: 1 addition & 1 deletion WheelWizard/Services/Endpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public static class Endpoints
/// <summary>
/// The base address for accessing room data
/// </summary>
public const string RwfcBaseAddress = "http://rwfc.net";
public const string RwfcBaseAddress = "https://rwfc.net";

/// <summary>
/// The base address for accessing the WheelWizard data (data that we control)
Expand Down
Loading
Loading