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>
877 lines
20 KiB
Markdown
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
|