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
17 changes: 17 additions & 0 deletions src/lib/deck/bracket.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,23 @@ describe("scoreBracket", () => {
);
});

it("names a card once when the deck holds several printings of it", () => {
const stats = makeStats({
bannedCards: ["Mana Crypt", "Griselbrand", "Mana Crypt"],
colorIdentityViolations: ["Lightning Bolt", "Lightning Bolt"],
gameChangersCount: 2,
gameChangersList: ["Sol Ring", "Sol Ring"],
});

expect(assertBracket(scoreBracket(makeDeck(), stats)).warnings).toEqual(
expect.arrayContaining([
"Banned cards in deck: Griselbrand, Mana Crypt",
"Color identity violations: Lightning Bolt",
"2 Game Changer(s): Sol Ring",
])
);
});

it("returns null for non-Commander formats", () => {
const deck = makeDeck({ format: "standard" });
const stats = makeStats();
Expand Down
3 changes: 2 additions & 1 deletion src/lib/deck/bracket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Deck, DeckStats, BracketScore } from "./types";
import type { SpellbookVariant } from "@/lib/combos/spellbook";
import { getCompanionDeckWarnings } from "./companion";
import { getFormatConfig } from "./formats";
import { sortedUniqueNames } from "./validation";

function clamp(value: number, min: number, max: number): number {
return Math.max(min, Math.min(max, value));
Expand Down Expand Up @@ -92,7 +93,7 @@ function countTwoCardInfiniteCombos(combos: SpellbookVariant[]): number {
}

function warningCardNames(names: readonly string[]): string {
return [...names].sort((left, right) => left.localeCompare(right, "en")).join(", ");
return sortedUniqueNames(names).join(", ");
}

/** Helper: generate ban/legality warnings */
Expand Down
15 changes: 12 additions & 3 deletions src/lib/deck/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,24 @@ export function validateCardForDeck(
};
}

/**
* Deduplicate names and order them case-insensitively, with a case-sensitive tiebreak.
* @param names - Card names; several printings of one card may repeat a name.
* @returns Each name once, independent of input order.
*/
export function sortedUniqueNames(names: Iterable<string>): string[] {
return [...new Set(names)].toSorted(
(left, right) => left.localeCompare(right, "en", { sensitivity: "base" }) || left.localeCompare(right)
);
}

/**
* List distinct card names in a stable, case-insensitive alphabetical order.
* @param cards - Deck rows to name; several rows may share a name.
* @returns Unique card names, independent of deck row order.
*/
export function sortedUniqueCardNames(cards: readonly DeckCard[]): string[] {
return [...new Set(cards.map((card) => card.name))].toSorted(
(left, right) => left.localeCompare(right, "en", { sensitivity: "base" }) || left.localeCompare(right)
);
return sortedUniqueNames(cards.map((card) => card.name));
}

function checkCardCount(allCards: DeckCard[], deckSize: number, errors: string[], warnings: string[]): void {
Expand Down
Loading