From f94bea3e742bf4eceeba096664106d50e41cfdb0 Mon Sep 17 00:00:00 2001 From: Toutsu Date: Thu, 28 May 2026 14:58:49 +0300 Subject: [PATCH] feat(shared): add GameSystem enum and Showcase DTOs Co-Authored-By: Claude Opus 4.7 --- src/GmRelay.Shared/Domain/GameSystem.cs | 88 +++++++++++++++++++ .../Features/Showcase/ShowcaseFilter.cs | 23 +++++ .../Features/Showcase/ShowcaseSessionDto.cs | 19 ++++ 3 files changed, 130 insertions(+) create mode 100644 src/GmRelay.Shared/Domain/GameSystem.cs create mode 100644 src/GmRelay.Shared/Features/Showcase/ShowcaseFilter.cs create mode 100644 src/GmRelay.Shared/Features/Showcase/ShowcaseSessionDto.cs diff --git a/src/GmRelay.Shared/Domain/GameSystem.cs b/src/GmRelay.Shared/Domain/GameSystem.cs new file mode 100644 index 0000000..639f757 --- /dev/null +++ b/src/GmRelay.Shared/Domain/GameSystem.cs @@ -0,0 +1,88 @@ +using System.Collections.Frozen; + +namespace GmRelay.Shared.Domain; + +public enum GameSystem +{ + Dnd5e, + Dnd3_5, + Dnd4e, + DnD2024, + Pathfinder1e, + Pathfinder2e, + Starfinder, + CallOfCthulhu, + WarhammerFantasy, + Warhammer40k, + DarkHeresy, + Shadowrun, + GURPS, + Fate, + SavageWorlds, + CyberpunkRed, + VampireTheMasquerade, + Lancer, + BladesInTheDark, + DungeonWorld, + Numenera, + CypherSystem, + Other +} + +public static class GameSystemExtensions +{ + private static readonly FrozenDictionary DisplayNames = + new Dictionary + { + [GameSystem.Dnd5e] = "D&D 5e", + [GameSystem.Dnd3_5] = "D&D 3.5", + [GameSystem.Dnd4e] = "D&D 4e", + [GameSystem.DnD2024] = "D&D 2024", + [GameSystem.Pathfinder1e] = "Pathfinder 1e", + [GameSystem.Pathfinder2e] = "Pathfinder 2e", + [GameSystem.Starfinder] = "Starfinder", + [GameSystem.CallOfCthulhu] = "Call of Cthulhu", + [GameSystem.WarhammerFantasy] = "Warhammer Fantasy", + [GameSystem.Warhammer40k] = "Warhammer 40,000", + [GameSystem.DarkHeresy] = "Dark Heresy", + [GameSystem.Shadowrun] = "Shadowrun", + [GameSystem.GURPS] = "GURPS", + [GameSystem.Fate] = "Fate", + [GameSystem.SavageWorlds] = "Savage Worlds", + [GameSystem.CyberpunkRed] = "Cyberpunk Red", + [GameSystem.VampireTheMasquerade] = "Vampire: The Masquerade", + [GameSystem.Lancer] = "Lancer", + [GameSystem.BladesInTheDark] = "Blades in the Dark", + [GameSystem.DungeonWorld] = "Dungeon World", + [GameSystem.Numenera] = "Numenera", + [GameSystem.CypherSystem] = "Cypher System", + [GameSystem.Other] = "Другое" + }.ToFrozenDictionary(); + + public static string ToDisplayName(this GameSystem system) => + DisplayNames.TryGetValue(system, out var name) ? name : "Другое"; + + public static GameSystem TryParseFuzzy(string input) + { + if (string.IsNullOrWhiteSpace(input)) + return GameSystem.Other; + + if (Enum.TryParse(input, true, out var exact)) + return exact; + + foreach (var system in Enum.GetValues()) + { + if (system == GameSystem.Other) + continue; + + var name = system.ToString(); + if (name.Contains(input, StringComparison.OrdinalIgnoreCase) || + input.Contains(name, StringComparison.OrdinalIgnoreCase)) + { + return system; + } + } + + return GameSystem.Other; + } +} diff --git a/src/GmRelay.Shared/Features/Showcase/ShowcaseFilter.cs b/src/GmRelay.Shared/Features/Showcase/ShowcaseFilter.cs new file mode 100644 index 0000000..b71c61e --- /dev/null +++ b/src/GmRelay.Shared/Features/Showcase/ShowcaseFilter.cs @@ -0,0 +1,23 @@ +namespace GmRelay.Shared.Features.Showcase; + +public sealed record ShowcaseFilter( + DateFilter Date = DateFilter.All, + SeatFilter Seats = SeatFilter.Any, + string? System = null, + bool? IsOneShot = null, + string? Format = null); + +public enum DateFilter +{ + Today, + Tomorrow, + ThisWeek, + All +} + +public enum SeatFilter +{ + Available, + Waitlist, + Any +} diff --git a/src/GmRelay.Shared/Features/Showcase/ShowcaseSessionDto.cs b/src/GmRelay.Shared/Features/Showcase/ShowcaseSessionDto.cs new file mode 100644 index 0000000..3c0e13e --- /dev/null +++ b/src/GmRelay.Shared/Features/Showcase/ShowcaseSessionDto.cs @@ -0,0 +1,19 @@ +namespace GmRelay.Shared.Features.Showcase; + +public sealed record ShowcaseSessionDto( + Guid Id, + Guid GroupId, + string GroupName, + string? GroupSlug, + string Title, + DateTime ScheduledAt, + string Status, + string? System, + bool IsOneShot, + string? Format, + int? DurationMinutes, + string? CoverImageUrl, + int? MaxPlayers, + int ActivePlayerCount, + int WaitlistedPlayerCount, + bool AllowDirectRegistration);