From b4287c55a8db2aef26279570017bb69a57fdc188 Mon Sep 17 00:00:00 2001 From: tiennm99 Date: Wed, 11 Mar 2026 04:39:00 +0000 Subject: [PATCH] test(03-02): add failing test for Scoring system - Created test suite with 5 test cases for score calculation - Tests cover base score (100), 0-turn bonus (150), 1-turn bonus (125) - Tests verify default to base score for invalid turn counts - Tests verify integer scores (no floating point) --- gsd-framework/src/__tests__/Scoring.test.ts | 33 ++++++++++++++++++ gsd-framework/src/matching/Scoring.ts | 37 +++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 gsd-framework/src/__tests__/Scoring.test.ts create mode 100644 gsd-framework/src/matching/Scoring.ts diff --git a/gsd-framework/src/__tests__/Scoring.test.ts b/gsd-framework/src/__tests__/Scoring.test.ts new file mode 100644 index 0000000..acef651 --- /dev/null +++ b/gsd-framework/src/__tests__/Scoring.test.ts @@ -0,0 +1,33 @@ +// src/__tests__/Scoring.test.ts - Test suite for Scoring system +import { describe, it, expect } from 'vitest'; +import { Scoring } from '../matching/Scoring'; + +describe('Scoring', () => { + describe('calculate', () => { + it('should return base score of 100 for 2-turn match', () => { + const score = Scoring.calculate(2); + expect(score).toBe(100); + }); + + it('should return 150 (50% bonus) for 0-turn match', () => { + const score = Scoring.calculate(0); + expect(score).toBe(150); + }); + + it('should return 125 (25% bonus) for 1-turn match', () => { + const score = Scoring.calculate(1); + expect(score).toBe(125); + }); + + it('should default to base score for invalid turn count', () => { + const score = Scoring.calculate(5); + expect(score).toBe(100); + }); + + it('should return integer scores (no floating point)', () => { + const score = Scoring.calculate(0); + expect(Number.isInteger(score)).toBe(true); + expect(score).toBe(150); + }); + }); +}); diff --git a/gsd-framework/src/matching/Scoring.ts b/gsd-framework/src/matching/Scoring.ts new file mode 100644 index 0000000..dddd03c --- /dev/null +++ b/gsd-framework/src/matching/Scoring.ts @@ -0,0 +1,37 @@ +// src/matching/Scoring.ts - Score calculation with complexity bonus +/** + * Scoring system that rewards players with complexity bonuses + * Fewer turns = higher score (harder to spot paths) + */ + +export class Scoring { + /** + * Base score for any successful match + */ + private static readonly BASE_SCORE = 100; + + /** + * Bonus multipliers based on path complexity (fewer turns = higher bonus) + * - 0 turns: 1.5x (50% bonus) - same row/col direct path + * - 1 turn: 1.25x (25% bonus) - one corner + * - 2 turns: 1.0x (base) - two corners (max allowed) + */ + private static readonly BONUS_MULTIPLIERS = { + 0: 1.5, // 50% bonus for 0-turn (same row/col) + 1: 1.25, // 25% bonus for 1-turn + 2: 1.0 // No bonus for 2-turn + } as const; + + /** + * Calculate score based on path complexity (number of turns) + * @param turns - Number of turns in the path (0, 1, or 2) + * @returns Integer score with complexity bonus applied + */ + static calculate(turns: number): number { + // Get multiplier for this turn count, default to base (1.0) if invalid + const multiplier = this.BONUS_MULTIPLIERS[turns as keyof typeof Scoring.BONUS_MULTIPLIERS] || 1.0; + + // Calculate score and ensure integer result + return Math.floor(this.BASE_SCORE * multiplier); + } +}