@namespace Shared.Pages @inject CardRenderingService CardRenderer @inject Shared.Services.CardPreviewService PreviewService @page "/decks/{Name}" Chrono CCG - @(deck?.Name ?? "Deck Details")
Back to Decks @if (deck == null) {

Deck not found.

} else {

@deck.Name

Deck Code:
@deck.DeckCode
@if (deck.Syndicates.Count > 0) {
@foreach (var f in deck.Syndicates) { @f }
}
@deck.Cards.Count cards @(deck.IsValid ? "Valid" : "Invalid") @if (!deck.IsValid) { @deck.ValidationMessage }
@if (deck.Keycards.Count > 0) {

Keycards

} @if (deck.Divers.Count > 0) {

Divers

}

Cards

@if (deck.Description != null) {

Description

@CardRenderer.RenderDescription(deck.Description, SelectCard, doc => PreviewService.SelectDoc(doc), PreviewService)
}

Opening Hand Simulator

@if (hand.Count == 0) { } else { @if (!hasMulliganed) { } }
@if (hand.Count > 0) {
@foreach (var card in hand) { var isDiver = deck.Divers.Contains(card.Name); var isSelected = mulliganSelected.Contains(card);
@if (!string.IsNullOrEmpty(card.ImageFile)) { @card.Name } else {
@card.Name
}
@if (isDiver) { Diver } @if (isSelected) {
}
}

@if (!hasMulliganed) { Select non-diver cards to mulligan. You can only mulligan once. } else { Mulligan used. }

}
}
@code { [Parameter] public string Name { get; set; } = ""; private DeckData? deck; private CardData? selectedCard; private bool HasImage => selectedCard?.ImageFile is { Length: > 0 } && selectedCard.ImageFile != "placeholder.png"; protected override void OnParametersSet() { var decoded = Uri.UnescapeDataString(Name); deck = DeckDatabase.Decks.FirstOrDefault(d => d.IsVisible && d.Name == decoded); } private static readonly Dictionary CardLookup = CardDatabase.Cards .Where(c => !string.IsNullOrWhiteSpace(c.Name)) .GroupBy(c => c.Name, StringComparer.OrdinalIgnoreCase) .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); private CardData? LookupCard(string cardName) { return CardLookup.GetValueOrDefault(cardName); } private void SelectCard(CardData? card) { selectedCard = card; } private void CloseDetail() { selectedCard = null; } private List hand = []; private HashSet mulliganSelected = []; private bool hasMulliganed = false; private bool canMulligan => mulliganSelected.Count > 0 && !hasMulliganed; private void DrawInitialHand() { if (deck == null) return; hand.Clear(); mulliganSelected.Clear(); hasMulliganed = false; var random = new Random(); // 1. Get Divers var divers = deck.Divers.Select(LookupCard).Where(c => c != null).Cast().ToList(); // 2. Get Main Deck (excluding divers if they are in the main list, though usually they are separate in data) var mainDeck = deck.Cards.Select(LookupCard).Where(c => c != null).Cast().ToList(); // Add 3 random non-diver cards from main deck var nonDivers = mainDeck.Where(c => !deck.Divers.Contains(c.Name)).OrderBy(_ => random.Next()).Take(4).ToList(); hand.AddRange(nonDivers); // Final shuffle of hand for display hand = hand.OrderBy(_ => random.Next()).ToList(); // Add 2 random divers if (divers.Count > 0) { var newHand = divers.Take(2).ToList(); newHand.AddRange(hand); hand = newHand; } } private void ToggleMulliganSelection(CardData card) { if (hasMulliganed) return; if (deck?.Divers.Contains(card.Name) == true) return; // Cannot mulligan divers if (mulliganSelected.Contains(card)) mulliganSelected.Remove(card); else mulliganSelected.Add(card); } private void Mulligan() { if (deck == null || hasMulliganed || mulliganSelected.Count == 0) return; var random = new Random(); var mainDeck = deck.Cards.Select(LookupCard).Where(c => c != null).Cast().ToList(); var nonDiversInDeck = mainDeck.Where(c => !deck.Divers.Contains(c.Name)).ToList(); // Filter out cards currently in hand var currentHandNames = hand.Select(c => c.Name).ToList(); var availablePool = nonDiversInDeck.Where(c => !currentHandNames.Contains(c.Name)).ToList(); var cardsToReplace = mulliganSelected.ToList(); foreach (var oldCard in cardsToReplace) { if (availablePool.Count > 0) { var newCardIdx = random.Next(availablePool.Count); var newCard = availablePool[newCardIdx]; var handIdx = hand.IndexOf(oldCard); if (handIdx != -1) { hand[handIdx] = newCard; } availablePool.RemoveAt(newCardIdx); } } mulliganSelected.Clear(); hasMulliganed = true; } private List<(int Cost, int Count)> GetManaDistribution() { if (deck == null) return []; var counts = new Dictionary(); for (var i = 0; i <= 10; i++) counts[i] = 0; foreach (var cardName in deck.Cards) { var card = LookupCard(cardName); if (card?.Cost != null) { var cost = card.Cost.Value; if (cost >= 10) cost = 10; counts[cost]++; } } return counts.OrderBy(x => x.Key).Select(x => (x.Key, x.Value)).ToList(); } }