chess/planning/DEVELOPER_GUIDE.md
Christoph Wagner 5ad0700b41 refactor: Consolidate repository structure - flatten from workspace pattern
Restructured project from nested workspace pattern to flat single-repo layout.
This eliminates redundant nesting and consolidates all project files under version control.

## Migration Summary

**Before:**
```
alex/ (workspace, not versioned)
├── chess-game/ (git repo)
│   ├── js/, css/, tests/
│   └── index.html
└── docs/ (planning, not versioned)
```

**After:**
```
alex/ (git repo, everything versioned)
├── js/, css/, tests/
├── index.html
├── docs/ (project documentation)
├── planning/ (historical planning docs)
├── .gitea/ (CI/CD)
└── CLAUDE.md (configuration)
```

## Changes Made

### Structure Consolidation
- Moved all chess-game/ contents to root level
- Removed redundant chess-game/ subdirectory
- Flattened directory structure (eliminated one nesting level)

### Documentation Organization
- Moved chess-game/docs/ → docs/ (project documentation)
- Moved alex/docs/ → planning/ (historical planning documents)
- Added CLAUDE.md (workspace configuration)
- Added IMPLEMENTATION_PROMPT.md (original project prompt)

### Version Control Improvements
- All project files now under version control
- Planning documents preserved in planning/ folder
- Merged .gitignore files (workspace + project)
- Added .claude/ agent configurations

### File Updates
- Updated .gitignore to include both workspace and project excludes
- Moved README.md to root level
- All import paths remain functional (relative paths unchanged)

## Benefits

 **Simpler Structure** - One level of nesting removed
 **Complete Versioning** - All documentation now in git
 **Standard Layout** - Matches open-source project conventions
 **Easier Navigation** - Direct access to all project files
 **CI/CD Compatible** - All workflows still functional

## Technical Validation

-  Node.js environment verified
-  Dependencies installed successfully
-  Dev server starts and responds
-  All core files present and accessible
-  Git repository functional

## Files Preserved

**Implementation Files:**
- js/ (3,517 lines of code)
- css/ (4 stylesheets)
- tests/ (87 test cases)
- index.html
- package.json

**CI/CD Pipeline:**
- .gitea/workflows/ci.yml
- .gitea/workflows/release.yml

**Documentation:**
- docs/ (12+ documentation files)
- planning/ (historical planning materials)
- README.md

**Configuration:**
- jest.config.js, babel.config.cjs, playwright.config.js
- .gitignore (merged)
- CLAUDE.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 10:05:26 +01:00

877 lines
20 KiB
Markdown

# Developer Guide - HTML Chess Game
## Table of Contents
1. [Development Environment](#development-environment)
2. [Project Structure](#project-structure)
3. [Development Workflow](#development-workflow)
4. [Testing Strategy](#testing-strategy)
5. [Debugging Guide](#debugging-guide)
6. [Performance Optimization](#performance-optimization)
7. [Code Style Guide](#code-style-guide)
8. [Deployment](#deployment)
9. [Troubleshooting](#troubleshooting)
---
## Development Environment
### Prerequisites
**Required:**
- Modern web browser (Chrome 60+, Firefox 54+, Safari 10.1+, Edge 79+)
- Text editor or IDE (VS Code recommended)
- Git for version control
**Optional:**
- Node.js (for local server and testing)
- Browser dev tools extensions
- Code formatters (Prettier recommended)
### Initial Setup
#### 1. Clone or Create Project
```bash
# Create new project
mkdir chess-game
cd chess-game
# Initialize git (optional)
git init
# Create project structure
mkdir -p {css,js/{game,pieces,moves,ui,utils},assets/pieces,tests/{unit,integration},docs}
```
#### 2. Install Development Tools (Optional)
```bash
# Initialize npm (for testing framework)
npm init -y
# Install dev dependencies (optional)
npm install --save-dev \
live-server \
eslint \
prettier \
jest
```
#### 3. Set Up Live Server
**Option 1: Using Python**
```bash
python3 -m http.server 8000
```
**Option 2: Using Node.js**
```bash
npx http-server -p 8000
```
**Option 3: Using VS Code Extension**
- Install "Live Server" extension
- Right-click `index.html` → "Open with Live Server"
#### 4. Configure Editor
**VS Code Settings (.vscode/settings.json):**
```json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"javascript.preferences.quoteStyle": "single",
"files.eol": "\n",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true
}
```
**ESLint Config (.eslintrc.json):**
```json
{
"env": {
"browser": true,
"es2021": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
"indent": ["error", 4],
"quotes": ["error", "single"],
"semi": ["error", "always"]
}
}
```
**Prettier Config (.prettierrc):**
```json
{
"singleQuote": true,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"trailingComma": "es5"
}
```
---
## Project Structure
### Directory Organization
```
chess-game/
├── index.html # Main entry point
├── package.json # npm configuration (optional)
├── .gitignore # Git ignore rules
├── .eslintrc.json # ESLint configuration
├── .prettierrc # Prettier configuration
├── css/ # Stylesheets
│ ├── board.css # Chess board styling
│ ├── pieces.css # Piece styling
│ └── ui.css # UI components
├── js/ # JavaScript modules
│ ├── main.js # Application entry point
│ │
│ ├── game/ # Game logic
│ │ ├── ChessGame.js # Main game controller
│ │ ├── Board.js # Board state management
│ │ └── GameState.js # Game state and history
│ │
│ ├── pieces/ # Piece implementations
│ │ ├── Piece.js # Base piece class
│ │ ├── Pawn.js # Pawn logic
│ │ ├── Knight.js # Knight logic
│ │ ├── Bishop.js # Bishop logic
│ │ ├── Rook.js # Rook logic
│ │ ├── Queen.js # Queen logic
│ │ └── King.js # King logic
│ │
│ ├── moves/ # Move validation
│ │ ├── MoveValidator.js # Move validation
│ │ ├── MoveGenerator.js # Legal move generation
│ │ └── SpecialMoves.js # Special moves
│ │
│ ├── ui/ # UI components
│ │ ├── BoardRenderer.js # Board rendering
│ │ ├── DragDropHandler.js # Drag-and-drop
│ │ └── UIController.js # UI state management
│ │
│ └── utils/ # Utilities
│ ├── notation.js # Chess notation
│ ├── storage.js # localStorage wrapper
│ └── helpers.js # Helper functions
├── assets/ # Static assets
│ └── pieces/ # Piece images (SVG)
│ ├── white-king.svg
│ ├── white-queen.svg
│ └── ...
├── tests/ # Test files
│ ├── unit/ # Unit tests
│ │ ├── Board.test.js
│ │ ├── pieces/
│ │ └── moves/
│ │
│ └── integration/ # Integration tests
│ └── gameplay.test.js
└── docs/ # Documentation
├── README.md
├── IMPLEMENTATION_GUIDE.md
├── API_REFERENCE.md
└── ...
```
### Module Dependencies
```
main.js
├── ChessGame.js
│ ├── Board.js
│ ├── GameState.js
│ └── MoveValidator.js
│ ├── Piece.js (and subclasses)
│ └── SpecialMoves.js
└── UIController.js
├── BoardRenderer.js
└── DragDropHandler.js
Utilities (used everywhere):
├── notation.js
├── storage.js
└── helpers.js
```
---
## Development Workflow
### 1. Feature Development Cycle
```bash
# 1. Create feature branch (if using git)
git checkout -b feature/castling-logic
# 2. Write failing test first (TDD)
# Edit tests/unit/moves/SpecialMoves.test.js
# 3. Run tests
npm test
# 4. Implement feature
# Edit js/moves/SpecialMoves.js
# 5. Run tests until passing
npm test
# 6. Refactor if needed
# Clean up code, improve performance
# 7. Commit changes
git add .
git commit -m "feat: implement castling logic"
# 8. Merge to main
git checkout main
git merge feature/castling-logic
```
### 2. Daily Development Routine
**Morning:**
1. Pull latest changes
2. Review open issues
3. Plan tasks for the day
4. Set up development environment
**During Development:**
1. Write test first (TDD)
2. Implement minimal code to pass
3. Refactor for quality
4. Commit frequently
5. Run full test suite periodically
**End of Day:**
1. Run full test suite
2. Commit all changes
3. Push to repository
4. Update task tracker
5. Document any blockers
### 3. Code Review Process
**Before Requesting Review:**
- [ ] All tests passing
- [ ] Code formatted and linted
- [ ] No console errors
- [ ] Documentation updated
- [ ] Self-review completed
**Review Checklist:**
- [ ] Code follows style guide
- [ ] Tests are comprehensive
- [ ] No performance regressions
- [ ] Edge cases handled
- [ ] Documentation accurate
---
## Testing Strategy
### Unit Testing
**Framework:** Jest (or your choice)
**Test Structure:**
```javascript
// tests/unit/pieces/Rook.test.js
import { Rook } from '../../../js/pieces/Rook.js';
import { Board } from '../../../js/game/Board.js';
describe('Rook', () => {
let board;
beforeEach(() => {
board = new Board();
board.clear(); // Start with empty board
});
describe('getValidMoves', () => {
it('should move vertically', () => {
const rook = new Rook('white', {row: 4, col: 4});
board.setPiece(4, 4, rook);
const moves = rook.getValidMoves(board);
const verticalMoves = moves.filter(m => m.col === 4);
expect(verticalMoves.length).toBe(7);
});
it('should be blocked by friendly pieces', () => {
const rook = new Rook('white', {row: 4, col: 4});
const blockingPawn = new Pawn('white', {row: 4, col: 6});
board.setPiece(4, 4, rook);
board.setPiece(4, 6, blockingPawn);
const moves = rook.getValidMoves(board);
const rightMoves = moves.filter(m => m.row === 4 && m.col > 4);
expect(rightMoves.length).toBe(1); // Only to col 5
});
it('should capture enemy pieces', () => {
const rook = new Rook('white', {row: 4, col: 4});
const enemyPawn = new Pawn('black', {row: 4, col: 6});
board.setPiece(4, 4, rook);
board.setPiece(4, 6, enemyPawn);
const moves = rook.getValidMoves(board);
const canCaptureEnemy = moves.some(m =>
m.row === 4 && m.col === 6
);
expect(canCaptureEnemy).toBe(true);
});
});
});
```
**Run Tests:**
```bash
# Run all tests
npm test
# Run specific file
npm test -- Rook.test.js
# Run with coverage
npm test -- --coverage
# Watch mode
npm test -- --watch
```
### Integration Testing
**Test Complete Scenarios:**
```javascript
// tests/integration/gameplay.test.js
describe('Complete Game Scenarios', () => {
it('should handle Scholar\'s Mate', () => {
const game = new ChessGame();
// Move sequence
expect(game.makeMove(6, 4, 4, 4).success).toBe(true); // e4
expect(game.makeMove(1, 4, 3, 4).success).toBe(true); // e5
expect(game.makeMove(7, 5, 4, 2).success).toBe(true); // Bc4
expect(game.makeMove(1, 1, 2, 2).success).toBe(true); // Nc6
expect(game.makeMove(7, 3, 3, 7).success).toBe(true); // Qh5
expect(game.makeMove(1, 6, 2, 5).success).toBe(true); // Nf6
expect(game.makeMove(3, 7, 1, 5).success).toBe(true); // Qxf7#
// Verify checkmate
expect(game.status).toBe('checkmate');
expect(game.winner).toBe('white');
});
it('should handle stalemate', () => {
const game = new ChessGame();
// Set up stalemate position
game.board.fromFEN('7k/5Q2/6K1/8/8/8/8/8 b - - 0 1');
expect(game.isStalemate('black')).toBe(true);
expect(game.status).toBe('stalemate');
});
});
```
### Manual Testing Checklist
**Before Each Release:**
- [ ] All piece types move correctly
- [ ] Special moves work (castling, en passant, promotion)
- [ ] Check detection accurate
- [ ] Checkmate detection accurate
- [ ] Stalemate detection accurate
- [ ] UI responsive and intuitive
- [ ] Save/load functionality works
- [ ] Undo/redo works correctly
- [ ] No console errors
- [ ] Performance acceptable
- [ ] Works in all target browsers
---
## Debugging Guide
### Browser Developer Tools
**Console Debugging:**
```javascript
// Add debug logging
console.log('Move validation:', {
piece: piece.type,
from: {row: fromRow, col: fromCol},
to: {row: toRow, col: toCol},
valid: result
});
// Use debugger statement
function makeMove(fromRow, fromCol, toRow, toCol) {
debugger; // Execution will pause here
const piece = this.board.getPiece(fromRow, fromCol);
// ...
}
// Group related logs
console.group('Move Validation');
console.log('Piece:', piece);
console.log('Valid moves:', validMoves);
console.log('Target:', {toRow, toCol});
console.groupEnd();
```
**Breakpoints:**
1. Open DevTools (F12)
2. Go to Sources tab
3. Find your file
4. Click line number to set breakpoint
5. Refresh page to trigger
**Watch Expressions:**
- Add `this.board.grid` to watch
- Add `this.gameState.moveHistory` to watch
- Add `this.currentTurn` to watch
### Common Issues and Solutions
#### Issue: Infinite Recursion in Check Detection
**Problem:**
```javascript
// Bad: Causes infinite loop
function isMoveLegal(board, piece, toRow, toCol) {
const validMoves = piece.getValidMoves(board); // Calls isMoveLegal again!
// ...
}
```
**Solution:**
```javascript
// Good: Separate concerns
function getValidMoves(board, piece) {
// Get moves without check validation
}
function getLegalMoves(board, piece) {
// Filter valid moves by check constraint
return getValidMoves(board, piece)
.filter(move => !leavesKingInCheck(board, piece, move));
}
```
#### Issue: Drag and Drop Not Working
**Checklist:**
- [ ] Element has `draggable="true"`
- [ ] Event listeners attached to correct elements
- [ ] `dataTransfer` used correctly
- [ ] `preventDefault()` called in `dragover`
**Debug:**
```javascript
boardElement.addEventListener('dragstart', (e) => {
console.log('Drag started:', e.target);
console.log('Data:', e.dataTransfer.getData('text/plain'));
});
boardElement.addEventListener('dragover', (e) => {
console.log('Drag over:', e.target);
e.preventDefault(); // Don't forget this!
});
```
#### Issue: Pieces Not Rendering
**Checklist:**
- [ ] CSS classes applied correctly
- [ ] Grid layout configured
- [ ] Z-index issues
- [ ] Unicode symbols or images loading
**Debug:**
```javascript
// Verify DOM structure
console.log('Board HTML:', boardElement.innerHTML);
console.log('Squares:', boardElement.querySelectorAll('.square').length);
console.log('Pieces:', boardElement.querySelectorAll('.piece').length);
```
### Performance Profiling
**Using Chrome DevTools:**
1. Open DevTools → Performance tab
2. Click Record
3. Perform action (e.g., make move)
4. Stop recording
5. Analyze timeline
**Identify Bottlenecks:**
- Excessive DOM manipulation
- Slow move validation
- Memory leaks
- Unnecessary re-renders
**Solution:**
```javascript
// Before: Slow
function updateBoard() {
boardElement.innerHTML = ''; // Triggers reflow
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
// Create and append elements
}
}
}
// After: Fast
function updateBoard() {
const fragment = document.createDocumentFragment();
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
// Create elements and append to fragment
}
}
boardElement.innerHTML = '';
boardElement.appendChild(fragment); // Single reflow
}
```
---
## Performance Optimization
### Minimize DOM Manipulation
**Use Document Fragments:**
```javascript
const fragment = document.createDocumentFragment();
// Add all elements to fragment
container.appendChild(fragment); // Single DOM update
```
**Batch Updates:**
```javascript
// Bad: Multiple reflows
element.style.width = '100px';
element.style.height = '100px';
element.style.backgroundColor = 'red';
// Good: Single reflow
element.style.cssText = 'width: 100px; height: 100px; background-color: red;';
```
### Memoize Expensive Calculations
```javascript
class Piece {
constructor() {
this._validMovesCache = null;
this._cacheValidUntil = null;
}
getValidMoves(board) {
const boardHash = board.getHash();
if (this._cacheValidUntil === boardHash) {
return this._validMovesCache;
}
// Calculate moves
this._validMovesCache = this.calculateValidMoves(board);
this._cacheValidUntil = boardHash;
return this._validMovesCache;
}
invalidateCache() {
this._validMovesCache = null;
this._cacheValidUntil = null;
}
}
```
### Debounce UI Updates
```javascript
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Usage
const updateUI = debounce(() => {
renderer.renderBoard(game.board, game.gameState);
}, 100);
```
### Optimize Event Handlers
**Use Event Delegation:**
```javascript
// Bad: Many listeners
squares.forEach(square => {
square.addEventListener('click', handleClick);
});
// Good: Single listener
boardElement.addEventListener('click', (e) => {
const square = e.target.closest('.square');
if (square) {
handleClick(square);
}
});
```
---
## Code Style Guide
### Naming Conventions
**Variables:**
```javascript
// camelCase for variables and functions
const currentTurn = 'white';
const isKingInCheck = true;
function makeMove(from, to) { }
```
**Classes:**
```javascript
// PascalCase for classes
class ChessGame { }
class MoveValidator { }
```
**Constants:**
```javascript
// UPPER_SNAKE_CASE for constants
const MAX_MOVES = 500;
const DEFAULT_FEN = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';
```
**Private Members:**
```javascript
// Prefix with underscore
class Piece {
constructor() {
this._cachedMoves = null;
}
}
```
### File Organization
**One class per file:**
```javascript
// Good: Rook.js
export class Rook extends Piece {
// ...
}
// Bad: pieces.js with all pieces
export class Rook { }
export class Bishop { }
export class Knight { }
```
**Related functions can be grouped:**
```javascript
// utils/helpers.js
export function clamp(value, min, max) { }
export function isInBounds(row, col) { }
export function getOppositeColor(color) { }
```
### Documentation
**JSDoc Comments:**
```javascript
/**
* Validates if a move is legal according to chess rules
*
* @param {Board} board - The current board state
* @param {Piece} piece - The piece to move
* @param {number} toRow - Target row (0-7)
* @param {number} toCol - Target column (0-7)
* @param {GameState} gameState - Current game state
* @returns {boolean} True if move is legal
*/
static isMoveLegal(board, piece, toRow, toCol, gameState) {
// ...
}
```
### Error Handling
**Use descriptive errors:**
```javascript
// Good
if (!piece) {
throw new Error(`No piece found at position (${row}, ${col})`);
}
// Bad
if (!piece) {
throw new Error('Invalid');
}
```
**Return result objects:**
```javascript
function makeMove(from, to) {
if (!isValid) {
return {
success: false,
error: 'Invalid move: piece cannot move there'
};
}
return {
success: true,
move: executedMove
};
}
```
---
## Deployment
### Pre-Deployment Checklist
- [ ] All tests passing
- [ ] No console errors
- [ ] Code minified (optional)
- [ ] Assets optimized
- [ ] Browser compatibility tested
- [ ] Performance acceptable
- [ ] Documentation updated
### Build Process (Optional)
If using build tools:
```bash
# Install build tools
npm install --save-dev webpack webpack-cli
# Create webpack.config.js
# Build for production
npm run build
```
### Static Hosting
**GitHub Pages:**
```bash
# Create gh-pages branch
git checkout -b gh-pages
# Push to GitHub
git push origin gh-pages
# Access at: https://username.github.io/chess-game
```
**Netlify:**
1. Connect GitHub repository
2. Set build command (if any)
3. Set publish directory
4. Deploy
**Vercel:**
```bash
npm install -g vercel
vercel deploy
```
### Performance Optimization for Production
**Minify CSS/JS:**
```bash
# CSS
npx cssnano css/board.css > dist/board.min.css
# JS
npx terser js/main.js -o dist/main.min.js
```
**Optimize Images:**
- Use SVG for piece images (scalable)
- Compress PNG/JPG if used
- Use appropriate formats
**Enable Compression:**
```
# .htaccess for Apache
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript
</IfModule>
```
---
## Troubleshooting
### Common Errors
**"Uncaught TypeError: Cannot read property 'grid' of undefined"**
- Board not initialized
- Check constructor calls
- Verify import statements
**"Maximum call stack size exceeded"**
- Infinite recursion
- Check move validation logic
- Verify event listener cleanup
**Drag and drop not working**
- Check draggable attribute
- Verify event listeners
- Call preventDefault() in dragover
### Getting Help
1. Check documentation
2. Review API reference
3. Search existing issues
4. Ask specific questions with code samples
---
**Next:** See [HANDOFF_CHECKLIST.md](HANDOFF_CHECKLIST.md) for implementation timeline