From 829c741e554d1490dd7a5bbc17f2a32f7195dc07 Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Thu, 23 Oct 2025 21:22:12 -0500 Subject: [PATCH] fix(card-sorting): adjust connecting paths for scaled cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When cards scale to 50% in correct positions, the connecting paths now properly connect to the center of the scaled cards instead of the original full-size positions. Updates the ContinuousSequencePath component to: - Track which cards are correctly positioned (and thus scaled) - Apply scale factor to card dimensions when calculating edge points - Pass scale information through cardCenters array This ensures paths connect smoothly to the visual center of all cards regardless of their scale. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../components/PlayingPhaseDrag.tsx | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/apps/web/src/arcade-games/card-sorting/components/PlayingPhaseDrag.tsx b/apps/web/src/arcade-games/card-sorting/components/PlayingPhaseDrag.tsx index 0ba190d8..7396e7a8 100644 --- a/apps/web/src/arcade-games/card-sorting/components/PlayingPhaseDrag.tsx +++ b/apps/web/src/arcade-games/card-sorting/components/PlayingPhaseDrag.tsx @@ -141,33 +141,47 @@ function ContinuousSequencePath({ correctOrder, viewportWidth, viewportHeight, + spectatorEducationalMode, + isSpectating, }: { cardStates: Map sequence: SortingCard[] correctOrder: SortingCard[] viewportWidth: number viewportHeight: number + spectatorEducationalMode: boolean + isSpectating: boolean }) { if (sequence.length < 2) return null - // Card dimensions + // Card dimensions (base size) const CARD_WIDTH = 140 const CARD_HEIGHT = 180 const CARD_HALF_WIDTH = CARD_WIDTH / 2 const CARD_HALF_HEIGHT = CARD_HEIGHT / 2 - // Get all card positions (card centers) + // Helper to check if a card is in correct position (and thus scaled to 50%) + const isCardCorrect = (card: SortingCard): boolean => { + const positionInSequence = sequence.findIndex((c) => c.id === card.id) + const isCorrectPosition = + positionInSequence >= 0 && correctOrder[positionInSequence]?.id === card.id + return isSpectating ? spectatorEducationalMode && isCorrectPosition : isCorrectPosition + } + + // Get all card positions (card centers) with scale information const cardCenters = sequence .map((card) => { const state = cardStates.get(card.id) if (!state) return null + const scale = isCardCorrect(card) ? 0.5 : 1 return { x: (state.x / 100) * viewportWidth + CARD_HALF_WIDTH, y: (state.y / 100) * viewportHeight + CARD_HALF_HEIGHT, cardId: card.id, + scale, } }) - .filter((p): p is { x: number; y: number; cardId: string } => p !== null) + .filter((p): p is { x: number; y: number; cardId: string; scale: number } => p !== null) if (cardCenters.length < 2) return null @@ -176,18 +190,23 @@ function ContinuousSequencePath({ centerX: number, centerY: number, dx: number, - dy: number + dy: number, + scale: number ): { x: number; y: number } => { // Normalize direction const length = Math.sqrt(dx * dx + dy * dy) const ndx = dx / length const ndy = dy / length + // Apply scale to card dimensions + const scaledHalfWidth = CARD_HALF_WIDTH * scale + const scaledHalfHeight = CARD_HALF_HEIGHT * scale + // Find which edge we hit first - const txRight = ndx > 0 ? CARD_HALF_WIDTH / ndx : Number.POSITIVE_INFINITY - const txLeft = ndx < 0 ? -CARD_HALF_WIDTH / ndx : Number.POSITIVE_INFINITY - const tyBottom = ndy > 0 ? CARD_HALF_HEIGHT / ndy : Number.POSITIVE_INFINITY - const tyTop = ndy < 0 ? -CARD_HALF_HEIGHT / ndy : Number.POSITIVE_INFINITY + const txRight = ndx > 0 ? scaledHalfWidth / ndx : Number.POSITIVE_INFINITY + const txLeft = ndx < 0 ? -scaledHalfWidth / ndx : Number.POSITIVE_INFINITY + const tyBottom = ndy > 0 ? scaledHalfHeight / ndy : Number.POSITIVE_INFINITY + const tyTop = ndy < 0 ? -scaledHalfHeight / ndy : Number.POSITIVE_INFINITY const t = Math.min(txRight, txLeft, tyBottom, tyTop) @@ -204,21 +223,21 @@ function ContinuousSequencePath({ const next = cardCenters[i + 1] const dx = next.x - center.x const dy = next.y - center.y - return findCardEdgePoint(center.x, center.y, dx, dy) + return findCardEdgePoint(center.x, center.y, dx, dy, center.scale) } if (i === cardCenters.length - 1) { // Last card: direction from previous card const prev = cardCenters[i - 1] const dx = center.x - prev.x const dy = center.y - prev.y - return findCardEdgePoint(center.x, center.y, dx, dy) + return findCardEdgePoint(center.x, center.y, dx, dy, center.scale) } // Middle cards: average direction between prev and next const prev = cardCenters[i - 1] const next = cardCenters[i + 1] const dx = next.x - prev.x const dy = next.y - prev.y - return findCardEdgePoint(center.x, center.y, dx, dy) + return findCardEdgePoint(center.x, center.y, dx, dy, center.scale) }) if (positions.length < 2) return null @@ -1763,6 +1782,8 @@ export function PlayingPhaseDrag() { correctOrder={state.correctOrder} viewportWidth={viewportDimensions.width} viewportHeight={viewportDimensions.height} + spectatorEducationalMode={spectatorEducationalMode} + isSpectating={isSpectating} /> )}