From cf84d4c54b7ba6df64864e94eeba79de0119e044 Mon Sep 17 00:00:00 2001 From: Ashton Anderson Date: Mon, 30 Mar 2026 14:00:48 -0400 Subject: [PATCH] Add round 2 candidates challenges --- src/constants/candidates.ts | 43 ++++++++++++++++++++++++++++++++++++- src/lib/positionLinks.ts | 4 +++- src/pages/candidates.tsx | 43 ++++++++++++++++++++++++++----------- 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/src/constants/candidates.ts b/src/constants/candidates.ts index 124ceb66..cc301f33 100644 --- a/src/constants/candidates.ts +++ b/src/constants/candidates.ts @@ -72,7 +72,48 @@ export const CANDIDATES_EXTRA_IDEAS: CandidateIdea[] = [ ] // Drop live tournament moments here as PGN or FEN during the event. -export const CANDIDATES_FEATURED_POSITIONS: CandidatePosition[] = [] +export const CANDIDATES_FEATURED_POSITIONS: CandidatePosition[] = [ + { + id: 'rd2-defend-like-hikaru', + title: 'Rd2 Challenge 1: Defend like Hikaru', + subtitle: 'Can you hold the position like Hikaru did?', + summary: 'Nakamura is under pressure. Black to move and defend accurately.', + tag: 'Featured', + accent: 'red', + fen: '2r3k1/2q2ppp/5n2/p1p1p3/4P2P/1PQ3P1/P4PB1/2R3K1 b - - 0 25', + playerColor: 'black', + maiaVersion: 'maia_kdd_1900', + targetMoveNumber: 8, + }, + { + id: 'rd2-pragg-french', + title: "Rd2 Challenge 2: Hold off Pragg's French", + subtitle: + 'Can you defend the White side after some inaccuracies in the French?', + summary: + 'White to move in a tense French structure. Defend the position accurately.', + tag: 'Featured', + accent: 'amber', + fen: 'r1b2rk1/6pp/ppqbpn2/2pp4/3P1P2/2N1B3/PPPQB1PP/4RR1K b - - 1 16', + playerColor: 'white', + maiaVersion: 'maia_kdd_1800', + targetMoveNumber: 8, + }, + { + id: 'rd2-be-like-bluebaum', + title: 'Rd2 Challenge 3: Be like Bluebaum', + subtitle: + 'Bluebaum had less space, but held the draw anyway. Try to do the same.', + summary: + 'Bluebaum-style defense and coordination. Black to move and find the right plan.', + tag: 'Featured', + accent: 'blue', + fen: '4rb1r/pp1k1pp1/2p1nnb1/3p2Np/3P3P/2P1NPP1/PP3K2/R1B2B1R b - - 3 19', + playerColor: 'black', + maiaVersion: 'maia_kdd_1900', + targetMoveNumber: 8, + }, +] // Warm-up cards keep the page useful before round one begins. export const CANDIDATES_WARMUP_POSITIONS: CandidatePosition[] = [ diff --git a/src/lib/positionLinks.ts b/src/lib/positionLinks.ts index 786d0d2c..6c9a255a 100644 --- a/src/lib/positionLinks.ts +++ b/src/lib/positionLinks.ts @@ -112,7 +112,9 @@ export const buildPositionPlayLink = (options: PositionLinkOptions): string => { const params = new URLSearchParams() const normalizedFen = normalizeFen(options.fen) const forcedPlayerColor = - options.forcedPlayerColor ?? inferPlayerColorFromFen(normalizedFen) + options.forcedPlayerColor ?? + options.playerColor ?? + inferPlayerColorFromFen(normalizedFen) params.set('fen', normalizedFen) params.set('maiaVersion', 'maia_kdd_1500') diff --git a/src/pages/candidates.tsx b/src/pages/candidates.tsx index 3135dfa6..ee82a711 100644 --- a/src/pages/candidates.tsx +++ b/src/pages/candidates.tsx @@ -55,6 +55,12 @@ const accentClasses: Record = { const completedAccentClass = 'border-emerald-300/35 bg-[radial-gradient(circle_at_top,rgba(52,211,153,0.18),transparent_62%),rgba(255,255,255,0.03)]' +const ChallengeSectionTitle: React.FC<{ title: string }> = ({ title }) => ( +
+

{title}

+
+) + const PositionBoard: React.FC<{ position: CandidatePosition completed?: boolean @@ -184,10 +190,6 @@ export default function CandidatesPage() { const [completedChallengeIds, setCompletedChallengeIds] = useState( [], ) - const positions = useMemo( - () => [...CANDIDATES_FEATURED_POSITIONS, ...CANDIDATES_WARMUP_POSITIONS], - [], - ) const completedChallengeId = typeof router.query.completedChallenge === 'string' ? router.query.completedChallenge @@ -242,7 +244,7 @@ export default function CandidatesPage() { FIDE Candidates Tournament 2026

- Round 1 + Round 2

- {positions.map((position) => ( - - ))} + {CANDIDATES_FEATURED_POSITIONS.length > 0 ? ( + <> + + {CANDIDATES_FEATURED_POSITIONS.map((position) => ( + + ))} + + ) : null} + {CANDIDATES_WARMUP_POSITIONS.length > 0 ? ( + <> + + {CANDIDATES_WARMUP_POSITIONS.map((position) => ( + + ))} + + ) : null}