mirror of
https://github.com/tiennm99/mathmax.git
synced 2026-09-18 00:19:09 +00:00
fix(sang-eratosthenes): keep the grid usable for primes above 50
rippling was raised before the stagger loop but lowered only inside the final timeout, so a prime with no multiple left on the 100-cell grid left the flag raised and rejected every later click. Affected 10 of the 25 primes on the grid.
This commit is contained in:
@@ -51,6 +51,14 @@ export function createGridState(buildAnnouncement) {
|
||||
markedPrimes = [...markedPrimes, n];
|
||||
const multiples = multiplesOf(n, 100);
|
||||
|
||||
// Every prime above 50 has no multiple left on a 100-cell grid. There is
|
||||
// nothing to stagger, and entering ripple mode would lock the grid for
|
||||
// good, because only the final timeout clears the flag.
|
||||
if (multiples.length === 0) {
|
||||
announcement = buildAnnouncement(n, multiples);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reducedMotion) {
|
||||
const next = new Map(crossings);
|
||||
for (const cell of multiples) {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { createGridState } from './grid-interaction.svelte.js';
|
||||
|
||||
/** Minimal announcement builder; the tests only care that it was called. */
|
||||
const build = (/** @type {number} */ p, /** @type {number[]} */ mults) =>
|
||||
`${p}: ${mults.length}`;
|
||||
|
||||
describe('createGridState — marking primes', () => {
|
||||
it('a prime with no multiple left on the grid does not lock it', () => {
|
||||
const grid = createGridState(build);
|
||||
|
||||
// 53 is prime and 2×53 = 106 is off the 100-cell grid, so there is
|
||||
// nothing to cross out.
|
||||
grid.handleCellActivate(53);
|
||||
expect(grid.rippling).toBe(false);
|
||||
expect(grid.markedPrimes).toContain(53);
|
||||
expect(grid.announcement).toBe('53: 0');
|
||||
|
||||
// The grid must still accept the next prime.
|
||||
grid.handleCellActivate(59);
|
||||
expect(grid.markedPrimes).toContain(59);
|
||||
});
|
||||
|
||||
it('every prime above 50 leaves the grid usable', () => {
|
||||
const grid = createGridState(build);
|
||||
for (const p of [53, 59, 61, 67, 71, 73, 79, 83, 89, 97]) {
|
||||
grid.handleCellActivate(p);
|
||||
expect(grid.rippling).toBe(false);
|
||||
}
|
||||
expect(grid.markedPrimes).toHaveLength(10);
|
||||
});
|
||||
|
||||
it('a prime with multiples enters ripple mode and blocks further clicks', () => {
|
||||
const grid = createGridState(build);
|
||||
grid.handleCellActivate(7); // 14, 21, … are on the grid
|
||||
expect(grid.rippling).toBe(true);
|
||||
|
||||
grid.handleCellActivate(11);
|
||||
expect(grid.markedPrimes).not.toContain(11);
|
||||
});
|
||||
|
||||
it('a composite is rejected and marks no prime', () => {
|
||||
const grid = createGridState(build);
|
||||
grid.handleCellActivate(9);
|
||||
expect(grid.markedPrimes).toHaveLength(0);
|
||||
expect(grid.shakeIndex).toBe(8);
|
||||
});
|
||||
|
||||
it('the same prime cannot be marked twice', () => {
|
||||
const grid = createGridState(build);
|
||||
grid.handleCellActivate(53);
|
||||
grid.handleCellActivate(53);
|
||||
expect(grid.markedPrimes).toEqual([53]);
|
||||
});
|
||||
|
||||
it('reset clears marks and unlocks the grid', () => {
|
||||
const grid = createGridState(build);
|
||||
grid.handleCellActivate(7);
|
||||
expect(grid.rippling).toBe(true);
|
||||
grid.handleReset();
|
||||
expect(grid.rippling).toBe(false);
|
||||
expect(grid.markedPrimes).toHaveLength(0);
|
||||
expect(grid.announcement).toBe('');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user