初始化项目并上传代码
This commit is contained in:
226
docs/superpowers/plans/2026-03-17-conway-life-demo.md
Normal file
226
docs/superpowers/plans/2026-03-17-conway-life-demo.md
Normal file
@@ -0,0 +1,226 @@
|
||||
# Conway Life Demo Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Build a direct-open Conway's Game of Life demo page with a modern visualization style, preset patterns, canvas-based simulation, and a clean teaching-plus-exploration flow.
|
||||
|
||||
**Architecture:** Keep the page build-free and local-file friendly: semantic markup in `index.html`, visual styling in `styles.css`, and a single browser script in `app.js`. Put Conway engine logic and state helpers in testable pure functions exported from `app.js`, while the DOM/controller layer wires those functions to the canvas UI.
|
||||
|
||||
**Tech Stack:** HTML5, CSS3, vanilla JavaScript, Canvas API, Node.js built-in test runner (`node --test`)
|
||||
|
||||
---
|
||||
|
||||
Note: this workspace is not a git repository, so commit steps are intentionally omitted.
|
||||
|
||||
## File Structure
|
||||
|
||||
- Create: `index.html` - page structure, content sections, script/style includes
|
||||
- Create: `styles.css` - theme variables, layout, cards, control panel, responsive styling, animation polish
|
||||
- Create: `app.js` - Conway engine, preset definitions, state helpers, canvas rendering, UI events
|
||||
- Create: `tests/life-demo.test.js` - Node tests for pure simulation and state logic
|
||||
|
||||
## Chunk 1: Build and test the Conway engine
|
||||
|
||||
### Task 1: Create the failing engine tests
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/life-demo.test.js`
|
||||
- Test: `tests/life-demo.test.js`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
```js
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const {
|
||||
createEmptyGrid,
|
||||
stepGrid,
|
||||
stampPattern,
|
||||
PATTERNS,
|
||||
} = require('../app.js');
|
||||
|
||||
test('blinker rotates after one generation', () => {
|
||||
const grid = createEmptyGrid(5, 5);
|
||||
grid[2][1] = 1;
|
||||
grid[2][2] = 1;
|
||||
grid[2][3] = 1;
|
||||
|
||||
const next = stepGrid(grid);
|
||||
|
||||
assert.deepEqual(next[1], [0, 0, 1, 0, 0]);
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `node --test tests/life-demo.test.js`
|
||||
Expected: FAIL because `app.js` or the exported functions do not exist yet.
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
```js
|
||||
function createEmptyGrid(rows, cols) {
|
||||
return Array.from({ length: rows }, () => Array(cols).fill(0));
|
||||
}
|
||||
```
|
||||
|
||||
Implement the smallest export set needed to pass:
|
||||
- `createEmptyGrid(rows, cols)`
|
||||
- `countLiveNeighbors(grid, row, col)`
|
||||
- `stepGrid(grid)`
|
||||
- `stampPattern(grid, pattern, offsetRow, offsetCol)`
|
||||
- `PATTERNS` for `glider`, `pulsar`, and `gosperGliderGun`
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `node --test tests/life-demo.test.js`
|
||||
Expected: PASS for the engine tests.
|
||||
|
||||
## Chunk 2: Add state helpers and page shell
|
||||
|
||||
### Task 2: Add failing tests for state helpers
|
||||
|
||||
**Files:**
|
||||
- Modify: `tests/life-demo.test.js`
|
||||
- Modify: `app.js`
|
||||
- Create: `index.html`
|
||||
- Create: `styles.css`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
Add tests for:
|
||||
|
||||
```js
|
||||
test('createInitialState seeds the default preset and starts paused', () => {
|
||||
const state = createInitialState({
|
||||
rows: 20,
|
||||
cols: 20,
|
||||
defaultPattern: 'pulsar',
|
||||
});
|
||||
|
||||
assert.equal(state.running, false);
|
||||
assert.equal(state.selectedPattern, 'pulsar');
|
||||
assert.equal(state.generation, 0);
|
||||
assert.ok(state.liveCount > 0);
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `node --test tests/life-demo.test.js`
|
||||
Expected: FAIL because `createInitialState` is not implemented yet.
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
Implement pure helpers:
|
||||
- `cloneGrid(grid)`
|
||||
- `countLiveCells(grid)`
|
||||
- `createInitialState({ rows, cols, defaultPattern })`
|
||||
- `randomizeGrid(grid, probability)`
|
||||
- `toggleCell(grid, row, col, forcedValue)`
|
||||
|
||||
At the same time, scaffold:
|
||||
- `index.html` with Hero, Lab, Rules, and Presets sections
|
||||
- `styles.css` with the modern visualization theme variables and responsive grid
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `node --test tests/life-demo.test.js`
|
||||
Expected: PASS for the new state-helper tests.
|
||||
|
||||
## Chunk 3: Wire controls, canvas rendering, and preset switching
|
||||
|
||||
### Task 3: Add failing tests for UI-facing state transitions
|
||||
|
||||
**Files:**
|
||||
- Modify: `tests/life-demo.test.js`
|
||||
- Modify: `app.js`
|
||||
- Modify: `index.html`
|
||||
- Modify: `styles.css`
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
Add tests for:
|
||||
|
||||
```js
|
||||
test('applyPreset replaces the grid, pauses playback, and resets generation', () => {
|
||||
const state = {
|
||||
...createInitialState({ rows: 25, cols: 25, defaultPattern: 'glider' }),
|
||||
running: true,
|
||||
generation: 12,
|
||||
};
|
||||
|
||||
const next = applyPreset(state, 'gosperGliderGun');
|
||||
|
||||
assert.equal(next.running, false);
|
||||
assert.equal(next.generation, 0);
|
||||
assert.equal(next.selectedPattern, 'gosperGliderGun');
|
||||
assert.ok(next.liveCount > state.liveCount);
|
||||
});
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `node --test tests/life-demo.test.js`
|
||||
Expected: FAIL because `applyPreset` is not implemented yet.
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
Implement:
|
||||
- `applyPreset(state, patternName)`
|
||||
- `advanceState(state)`
|
||||
- `setSpeed(state, speed)`
|
||||
- `getSpeedLabel(speed)`
|
||||
|
||||
Then wire browser behavior:
|
||||
- draw the grid on a `canvas`
|
||||
- support play/pause, step, clear, randomize, reset preset, and speed controls
|
||||
- support click and drag painting on the canvas
|
||||
- update status text, generation count, live-count, and active preset styling
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `node --test tests/life-demo.test.js`
|
||||
Expected: PASS for the state-transition tests.
|
||||
|
||||
## Chunk 4: Polish visual details and run end-to-end verification
|
||||
|
||||
### Task 4: Finish presentation details and verify manually
|
||||
|
||||
**Files:**
|
||||
- Modify: `index.html`
|
||||
- Modify: `styles.css`
|
||||
- Modify: `app.js`
|
||||
- Test: `tests/life-demo.test.js`
|
||||
|
||||
- [ ] **Step 1: Refine the visuals**
|
||||
|
||||
Complete:
|
||||
- luminous background gradients and grid accents
|
||||
- polished cards and control panel surfaces
|
||||
- hover/focus states
|
||||
- responsive stacking for smaller screens
|
||||
- subtle canvas/section entrance motion
|
||||
|
||||
- [ ] **Step 2: Run automated tests**
|
||||
|
||||
Run: `node --test tests/life-demo.test.js`
|
||||
Expected: PASS with zero failures.
|
||||
|
||||
- [ ] **Step 3: Run manual verification**
|
||||
|
||||
Open: `index.html`
|
||||
|
||||
Verify:
|
||||
- page opens directly without a dev server
|
||||
- pulsar loads by default and the simulation starts paused
|
||||
- controls behave correctly
|
||||
- each preset loads and pauses correctly
|
||||
- editing by click/drag works
|
||||
- desktop and narrow layouts both remain usable
|
||||
|
||||
- [ ] **Step 4: Record any gaps**
|
||||
|
||||
If a browser-only issue appears, fix it and rerun:
|
||||
- `node --test tests/life-demo.test.js`
|
||||
- manual browser verification of `index.html`
|
||||
Reference in New Issue
Block a user