BREAKING CHANGES: - Remove timeLimit from GameOptions (use gameOver function instead) - Remove finalScore from ScoreManager (pure data collection only) - Remove rows/cols parameters from useScore - Remove finalScore calculation logic from useScore hook ADDITIONS: - Create calculateMazeScore() utility function - ScoreManager now only returns raw metrics: timeValue, keystrokes, optimalSteps, efficiency, distToKey, distToExit - Score calculation moved to consumer (calculateMazeScore takes scoreManager + mazeSize) - Example app now uses calculateMazeScore to compute final score on game-won BENEFITS: - ScoreManager is now a pure data collector with no side effects - Scoring algorithm is reusable and testable in isolation - Game-over conditions fully controlled via gameOver option - Clear separation of concerns: collection vs calculation
31 lines
1007 B
TypeScript
31 lines
1007 B
TypeScript
import type { ScoreManager } from './types';
|
||
|
||
/**
|
||
* Calculate the final maze score based on performance metrics
|
||
*
|
||
* Formula:
|
||
* Base Score = 1000 - (time penalty) - (keystroke penalty)
|
||
* Size Multiplier = max(1.0, (mazeSize) / 500)
|
||
* Final Score = min(1000, max(0, round(Base Score × Size Multiplier)))
|
||
*
|
||
* Penalties:
|
||
* - Time Penalty = seconds / 10
|
||
* - Keystroke Penalty = keystrokes / 2
|
||
*
|
||
* @param scoreManager - Current score metrics
|
||
* @param mazeSize - Total cells in maze (rows * cols)
|
||
* @returns Final score between 0-1000
|
||
*/
|
||
export function calculateMazeScore(scoreManager: ScoreManager, mazeSize: number): number {
|
||
const seconds = scoreManager.timeValue / 1000;
|
||
|
||
const timePenalty = seconds / 10;
|
||
const keystrokePenalty = scoreManager.keystrokes / 2;
|
||
const sizeMultiplier = Math.max(1.0, mazeSize / 500);
|
||
|
||
const baseScore = 1000 - timePenalty - keystrokePenalty;
|
||
const score = Math.min(1000, Math.max(0, Math.round(baseScore * sizeMultiplier)));
|
||
|
||
return score;
|
||
}
|