Files
vim-maze/UNIFIED_API_UPDATES.md
T
pastilhas b962ebf214 docs: add UNIFIED_API update recommendations
- Provide detailed before/after examples for all sections
- Document new gameOver pattern with flexible function-based conditions
- Explain migration path for games updating to this pattern
- Highlight benefits: pure data collection, separation of concerns, flexibility
- Guide for updating root UNIFIED_API.md to reflect vim-maze v2.3 changes
2025-11-02 17:09:21 +00:00

269 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UNIFIED_API.md Update Recommendations
This document outlines the changes needed in `/vimazing/games/UNIFIED_API.md` to reflect the scoring refactor implemented in vim-maze v2.3.0.
## Summary of Changes
Vim-maze has implemented a new pattern for score management:
- **ScoreManager** is now a pure data collector (no score calculation)
- **Score calculation** moved to consumer (via utility function or custom logic)
- **Game-over conditions** are fully flexible and consumer-controlled
## Required Updates
### 1. Example Entry Point (Line ~100)
**OLD:**
```typescript
// vim-maze
useGame({ rows: 24, cols: 32, timeLimit: 600 })
```
**NEW:**
```typescript
// vim-maze (with custom game-over condition)
useGame({
rows: 24,
cols: 32,
gameOver: (sm) => sm.timeValue >= 600000 // 10 minutes in milliseconds
})
```
### 2. Score Manager Type (Line ~189-201)
**OLD:**
```typescript
type ScoreManager = {
// Required Timing
timeValue: number; // Current time in milliseconds
// Required Metrics
totalKeystrokes: number; // Total keys pressed
// Required Result
finalScore: number | null; // 0-1000 (null until game-won)
// Optional: Game-specific metrics
// [additional fields as needed]
};
```
**NEW:**
```typescript
type ScoreManager = {
// Required Timing
timeValue: number; // Current time in milliseconds
// Required Metrics
totalKeystrokes: number; // Total keys pressed
// Optional: Game-specific metrics
// [additional fields as needed]
// NOTE: finalScore removed - calculation moved to consumer
};
```
**Add note:**
```
**Important:** ScoreManager is now a pure data collector.
Score calculation has been moved to the consumer.
Games should provide a utility function like `calculateScore()`
or instructions for score calculation in their documentation.
```
### 3. GameOptions Examples (Line ~222-230)
**OLD:**
```typescript
// vim-maze
type GameOptions = {
rows: number;
cols: number;
timeLimit?: number;
};
```
**NEW:**
```typescript
// vim-maze
type GameOptions = {
rows: number;
cols: number;
gameOver?: boolean | ((scoreManager: ScoreManager) => boolean);
};
```
### 4. Scoring Implementation Section (Line ~257-265)
**OLD:**
```typescript
**vim-maze approach:**
```typescript
// Size-based: time + keystrokes × maze size
const baseScore = 1000 - timePenalty - keystrokePenalty;
const sizeMultiplier = max(1.0, (rows × cols) / 500);
const finalScore = min(1000, baseScore × sizeMultiplier);
```
```
**NEW:**
```typescript
**vim-maze approach (v2.3+):**
```typescript
// Pure data collection in ScoreManager
const scoreManager = useScore({ /* dependencies */ });
// scoreManager returns: { timeValue, keystrokes, optimalSteps, efficiency, ... }
// Score calculation moved to consumer
import { calculateMazeScore } from '@vimazing/vim-maze';
const finalScore = calculateMazeScore(scoreManager, mazeSize);
// Base: 1000 - (time/10) - (keystrokes/2)
// Then: multiply by size factor = max(1.0, (rows × cols) / 500)
// Final: clamp to 0-1000
```
```
### 5. Scoring Requirements Section (Line ~203-208)
**OLD:**
```
**Scoring Requirements:**
- Score range: 0-1000 (capped)
- Score calculated on game-won
- Based on time and keystrokes (minimum)
- Can include game-specific penalties/bonuses
```
**NEW:**
```
**Scoring Requirements:**
- Score range: 0-1000 (capped)
- Based on time and keystrokes (minimum)
- Can include game-specific penalties/bonuses
- **NEW:** Score calculation moved to consumer via utility function
- Games should provide `calculateScore()` or similar utility
- Games should document their scoring formula clearly
```
### 6. Game-Over Conditions Pattern (New Section)
Add a new subsection after "Scoring Requirements":
```markdown
### Game-Over Conditions
Starting with vim-maze v2.3+, games have full control over game-over conditions:
```typescript
type GameOptions = {
// ...game-specific options...
gameOver?: boolean | ((scoreManager: ScoreManager) => boolean);
};
```
**Examples:**
```typescript
// Static game-over
useGame({ rows: 24, cols: 32, gameOver: true })
// Time-based
useGame({
rows: 24,
cols: 32,
gameOver: (sm) => sm.timeValue >= 600000 // 10 minutes
})
// Efficiency-based
useGame({
rows: 24,
cols: 32,
gameOver: (sm) => sm.efficiency > 150 // >150% keystrokes
})
// Combined conditions
useGame({
rows: 24,
cols: 32,
gameOver: (sm) => sm.efficiency > 150 || sm.timeValue >= 600000
})
```
**Benefits:**
- No hardcoded game-over logic in libraries
- Consumers define win/loss conditions
- Flexible for tournaments, variations, custom rules
```
### 7. Hook Specifications - useScore Section (Line ~424+)
Find and update the useScore section:
**OLD:**
```typescript
export function useScore(/* dependencies */) {
// ...
const [timeValue, setTimeValue] = useState(0);
const [finalScore, setFinalScore] = useState<number | null>(null);
// Calculate score on game-won
useEffect(() => {
if (gameStatus === 'game-won') {
const score = calculateScore(timeValue, totalKeystrokes);
setFinalScore(Math.min(1000, Math.max(0, score)));
}
}, [gameStatus]);
return {
timeValue,
totalKeystrokes,
finalScore,
// Additional metrics
};
}
```
**NEW:**
```typescript
export function useScore(/* dependencies */) {
// Returns raw metrics only - no calculation
// Score calculation moved to consumer
return {
timeValue,
totalKeystrokes,
// Additional game-specific metrics
// finalScore removed - consumer responsibility
};
}
```
Add note:
```
**Change in v2.3+:** ScoreManager is now a pure data collector.
All score calculation has been moved to the consumer.
This provides flexibility and allows games to:
- Provide utility functions for standard scoring
- Allow consumers to implement custom scoring
- Keep the hook focused on metrics collection
```
## Migration Guide for Games
For games updating to this pattern:
1. Remove `finalScore` from `ScoreManager` type
2. Remove score calculation logic from `useScore` hook
3. Export a `calculateScore()` utility function
4. Update `gameOver` option to accept function receiving `scoreManager`
5. Remove `timeLimit` logic from `useScore` (delegate to consumer)
6. Document the new scoring approach in gameInfo
## Benefits of This Pattern
✅ **Pure Data Collection** - ScoreManager has no side effects
✅ **Separation of Concerns** - Scoring logic is independent
✅ **Flexibility** - Consumers control both scoring and game-over
✅ **Testability** - Scoring functions can be tested in isolation
✅ **Reusability** - Metrics available for any custom logic
✅ **Clarity** - Clear boundaries between collection and calculation