@nawa-captcha/server 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -2
- package/dist/binding.d.ts +22 -0
- package/dist/binding.d.ts.map +1 -0
- package/dist/binding.js +46 -0
- package/dist/binding.js.map +1 -0
- package/dist/catalog.d.ts +12 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +42 -0
- package/dist/catalog.js.map +1 -0
- package/dist/crypto.d.ts +44 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +108 -0
- package/dist/crypto.js.map +1 -0
- package/dist/engine.d.ts +245 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +407 -0
- package/dist/engine.js.map +1 -0
- package/dist/express.d.ts +47 -0
- package/dist/express.d.ts.map +1 -0
- package/dist/express.js +107 -0
- package/dist/express.js.map +1 -0
- package/dist/heuristics.d.ts +33 -0
- package/dist/heuristics.d.ts.map +1 -0
- package/dist/heuristics.js +152 -0
- package/dist/heuristics.js.map +1 -0
- package/dist/http.d.ts +51 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +70 -0
- package/dist/http.js.map +1 -0
- package/dist/i18n.d.ts +237 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +92 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/primitives.browser.d.ts +15 -0
- package/dist/primitives.browser.d.ts.map +1 -0
- package/dist/primitives.browser.js +328 -0
- package/dist/primitives.browser.js.map +1 -0
- package/dist/primitives.d.ts +17 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +58 -0
- package/dist/primitives.js.map +1 -0
- package/dist/puzzles/accessible.d.ts +43 -0
- package/dist/puzzles/accessible.d.ts.map +1 -0
- package/dist/puzzles/accessible.js +317 -0
- package/dist/puzzles/accessible.js.map +1 -0
- package/dist/puzzles/audio.d.ts +42 -0
- package/dist/puzzles/audio.d.ts.map +1 -0
- package/dist/puzzles/audio.js +109 -0
- package/dist/puzzles/audio.js.map +1 -0
- package/dist/puzzles/biggest.d.ts +5 -0
- package/dist/puzzles/biggest.d.ts.map +1 -0
- package/dist/puzzles/biggest.js +40 -0
- package/dist/puzzles/biggest.js.map +1 -0
- package/dist/puzzles/clock.d.ts +8 -0
- package/dist/puzzles/clock.d.ts.map +1 -0
- package/dist/puzzles/clock.js +68 -0
- package/dist/puzzles/clock.js.map +1 -0
- package/dist/puzzles/color-name.d.ts +5 -0
- package/dist/puzzles/color-name.d.ts.map +1 -0
- package/dist/puzzles/color-name.js +73 -0
- package/dist/puzzles/color-name.js.map +1 -0
- package/dist/puzzles/common.d.ts +75 -0
- package/dist/puzzles/common.d.ts.map +1 -0
- package/dist/puzzles/common.js +268 -0
- package/dist/puzzles/common.js.map +1 -0
- package/dist/puzzles/count.d.ts +8 -0
- package/dist/puzzles/count.d.ts.map +1 -0
- package/dist/puzzles/count.js +38 -0
- package/dist/puzzles/count.js.map +1 -0
- package/dist/puzzles/dice.d.ts +8 -0
- package/dist/puzzles/dice.d.ts.map +1 -0
- package/dist/puzzles/dice.js +61 -0
- package/dist/puzzles/dice.js.map +1 -0
- package/dist/puzzles/find-shape.d.ts +8 -0
- package/dist/puzzles/find-shape.d.ts.map +1 -0
- package/dist/puzzles/find-shape.js +45 -0
- package/dist/puzzles/find-shape.js.map +1 -0
- package/dist/puzzles/grid.d.ts +44 -0
- package/dist/puzzles/grid.d.ts.map +1 -0
- package/dist/puzzles/grid.js +33 -0
- package/dist/puzzles/grid.js.map +1 -0
- package/dist/puzzles/hold.d.ts +24 -0
- package/dist/puzzles/hold.d.ts.map +1 -0
- package/dist/puzzles/hold.js +68 -0
- package/dist/puzzles/hold.js.map +1 -0
- package/dist/puzzles/icons-objects.d.ts +3 -0
- package/dist/puzzles/icons-objects.d.ts.map +1 -0
- package/dist/puzzles/icons-objects.js +5 -0
- package/dist/puzzles/icons-objects.js.map +1 -0
- package/dist/puzzles/icons-weather.d.ts +3 -0
- package/dist/puzzles/icons-weather.d.ts.map +1 -0
- package/dist/puzzles/icons-weather.js +5 -0
- package/dist/puzzles/icons-weather.js.map +1 -0
- package/dist/puzzles/icons.d.ts +14 -0
- package/dist/puzzles/icons.d.ts.map +1 -0
- package/dist/puzzles/icons.js +49 -0
- package/dist/puzzles/icons.js.map +1 -0
- package/dist/puzzles/index.d.ts +63 -0
- package/dist/puzzles/index.d.ts.map +1 -0
- package/dist/puzzles/index.js +93 -0
- package/dist/puzzles/index.js.map +1 -0
- package/dist/puzzles/jigsaw.d.ts +22 -0
- package/dist/puzzles/jigsaw.d.ts.map +1 -0
- package/dist/puzzles/jigsaw.js +38 -0
- package/dist/puzzles/jigsaw.js.map +1 -0
- package/dist/puzzles/math-compare.d.ts +8 -0
- package/dist/puzzles/math-compare.d.ts.map +1 -0
- package/dist/puzzles/math-compare.js +47 -0
- package/dist/puzzles/math-compare.js.map +1 -0
- package/dist/puzzles/math.d.ts +16 -0
- package/dist/puzzles/math.d.ts.map +1 -0
- package/dist/puzzles/math.js +106 -0
- package/dist/puzzles/math.js.map +1 -0
- package/dist/puzzles/maze.d.ts +18 -0
- package/dist/puzzles/maze.d.ts.map +1 -0
- package/dist/puzzles/maze.js +138 -0
- package/dist/puzzles/maze.js.map +1 -0
- package/dist/puzzles/odd-one-out.d.ts +5 -0
- package/dist/puzzles/odd-one-out.d.ts.map +1 -0
- package/dist/puzzles/odd-one-out.js +36 -0
- package/dist/puzzles/odd-one-out.js.map +1 -0
- package/dist/puzzles/odd-rotation.d.ts +8 -0
- package/dist/puzzles/odd-rotation.d.ts.map +1 -0
- package/dist/puzzles/odd-rotation.js +48 -0
- package/dist/puzzles/odd-rotation.js.map +1 -0
- package/dist/puzzles/order-numbers.d.ts +5 -0
- package/dist/puzzles/order-numbers.d.ts.map +1 -0
- package/dist/puzzles/order-numbers.js +32 -0
- package/dist/puzzles/order-numbers.js.map +1 -0
- package/dist/puzzles/order-size.d.ts +5 -0
- package/dist/puzzles/order-size.d.ts.map +1 -0
- package/dist/puzzles/order-size.js +30 -0
- package/dist/puzzles/order-size.js.map +1 -0
- package/dist/puzzles/order-time.d.ts +5 -0
- package/dist/puzzles/order-time.d.ts.map +1 -0
- package/dist/puzzles/order-time.js +27 -0
- package/dist/puzzles/order-time.js.map +1 -0
- package/dist/puzzles/order.d.ts +30 -0
- package/dist/puzzles/order.d.ts.map +1 -0
- package/dist/puzzles/order.js +61 -0
- package/dist/puzzles/order.js.map +1 -0
- package/dist/puzzles/pairs.d.ts +15 -0
- package/dist/puzzles/pairs.d.ts.map +1 -0
- package/dist/puzzles/pairs.js +63 -0
- package/dist/puzzles/pairs.js.map +1 -0
- package/dist/puzzles/pattern.d.ts +8 -0
- package/dist/puzzles/pattern.d.ts.map +1 -0
- package/dist/puzzles/pattern.js +68 -0
- package/dist/puzzles/pattern.js.map +1 -0
- package/dist/puzzles/pow.d.ts +23 -0
- package/dist/puzzles/pow.d.ts.map +1 -0
- package/dist/puzzles/pow.js +52 -0
- package/dist/puzzles/pow.js.map +1 -0
- package/dist/puzzles/rotate-match.d.ts +8 -0
- package/dist/puzzles/rotate-match.d.ts.map +1 -0
- package/dist/puzzles/rotate-match.js +34 -0
- package/dist/puzzles/rotate-match.js.map +1 -0
- package/dist/puzzles/rotate-object.d.ts +5 -0
- package/dist/puzzles/rotate-object.d.ts.map +1 -0
- package/dist/puzzles/rotate-object.js +33 -0
- package/dist/puzzles/rotate-object.js.map +1 -0
- package/dist/puzzles/rotate.d.ts +24 -0
- package/dist/puzzles/rotate.d.ts.map +1 -0
- package/dist/puzzles/rotate.js +40 -0
- package/dist/puzzles/rotate.js.map +1 -0
- package/dist/puzzles/shadow-drag.d.ts +20 -0
- package/dist/puzzles/shadow-drag.d.ts.map +1 -0
- package/dist/puzzles/shadow-drag.js +64 -0
- package/dist/puzzles/shadow-drag.js.map +1 -0
- package/dist/puzzles/shadow-pick.d.ts +5 -0
- package/dist/puzzles/shadow-pick.d.ts.map +1 -0
- package/dist/puzzles/shadow-pick.js +38 -0
- package/dist/puzzles/shadow-pick.js.map +1 -0
- package/dist/puzzles/slide-unlock.d.ts +11 -0
- package/dist/puzzles/slide-unlock.d.ts.map +1 -0
- package/dist/puzzles/slide-unlock.js +79 -0
- package/dist/puzzles/slide-unlock.js.map +1 -0
- package/dist/puzzles/slider.d.ts +23 -0
- package/dist/puzzles/slider.d.ts.map +1 -0
- package/dist/puzzles/slider.js +74 -0
- package/dist/puzzles/slider.js.map +1 -0
- package/dist/puzzles/spell.d.ts +8 -0
- package/dist/puzzles/spell.d.ts.map +1 -0
- package/dist/puzzles/spell.js +41 -0
- package/dist/puzzles/spell.js.map +1 -0
- package/dist/puzzles/story.d.ts +5 -0
- package/dist/puzzles/story.d.ts.map +1 -0
- package/dist/puzzles/story.js +101 -0
- package/dist/puzzles/story.js.map +1 -0
- package/dist/puzzles/symmetry.d.ts +8 -0
- package/dist/puzzles/symmetry.d.ts.map +1 -0
- package/dist/puzzles/symmetry.js +49 -0
- package/dist/puzzles/symmetry.js.map +1 -0
- package/dist/puzzles/tap-order.d.ts +20 -0
- package/dist/puzzles/tap-order.d.ts.map +1 -0
- package/dist/puzzles/tap-order.js +37 -0
- package/dist/puzzles/tap-order.js.map +1 -0
- package/dist/puzzles/trace-letters.d.ts +5 -0
- package/dist/puzzles/trace-letters.d.ts.map +1 -0
- package/dist/puzzles/trace-letters.js +19 -0
- package/dist/puzzles/trace-letters.js.map +1 -0
- package/dist/puzzles/trace.d.ts +32 -0
- package/dist/puzzles/trace.d.ts.map +1 -0
- package/dist/puzzles/trace.js +81 -0
- package/dist/puzzles/trace.js.map +1 -0
- package/dist/render/audio.d.ts +53 -0
- package/dist/render/audio.d.ts.map +1 -0
- package/dist/render/audio.js +236 -0
- package/dist/render/audio.js.map +1 -0
- package/dist/render/clock.d.ts +6 -0
- package/dist/render/clock.d.ts.map +1 -0
- package/dist/render/clock.js +23 -0
- package/dist/render/clock.js.map +1 -0
- package/dist/render/glyphs.d.ts +18 -0
- package/dist/render/glyphs.d.ts.map +1 -0
- package/dist/render/glyphs.js +70 -0
- package/dist/render/glyphs.js.map +1 -0
- package/dist/render/pictograms.d.ts +60 -0
- package/dist/render/pictograms.d.ts.map +1 -0
- package/dist/render/pictograms.js +167 -0
- package/dist/render/pictograms.js.map +1 -0
- package/dist/render/png.d.ts +11 -0
- package/dist/render/png.d.ts.map +1 -0
- package/dist/render/png.js +107 -0
- package/dist/render/png.js.map +1 -0
- package/dist/render/raster.d.ts +61 -0
- package/dist/render/raster.d.ts.map +1 -0
- package/dist/render/raster.js +389 -0
- package/dist/render/raster.js.map +1 -0
- package/dist/render/shapes.d.ts +25 -0
- package/dist/render/shapes.d.ts.map +1 -0
- package/dist/render/shapes.js +157 -0
- package/dist/render/shapes.js.map +1 -0
- package/dist/rng.d.ts +25 -0
- package/dist/rng.d.ts.map +1 -0
- package/dist/rng.js +93 -0
- package/dist/rng.js.map +1 -0
- package/dist/selection.d.ts +54 -0
- package/dist/selection.d.ts.map +1 -0
- package/dist/selection.js +85 -0
- package/dist/selection.js.map +1 -0
- package/dist/store.d.ts +66 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +100 -0
- package/dist/store.js.map +1 -0
- package/dist/tokens.d.ts +70 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +103 -0
- package/dist/tokens.js.map +1 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +61 -0
- package/dist/types.js.map +1 -0
- package/package.json +68 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../src/puzzles/story.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,EAAoC,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AA+EpG,8FAA8F;AAC9F,eAAO,MAAM,KAAK,EAAE,gBAAgB,CAAC,aAAa,EAAE,WAAW,CAmB9D,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { prompt, STORIES } from '../i18n.js';
|
|
2
|
+
import { hsl } from '../render/raster.js';
|
|
3
|
+
import { checkOrder } from './common.js';
|
|
4
|
+
import { orderChallenge, tileCanvas, TILE } from './order.js';
|
|
5
|
+
const T = TILE;
|
|
6
|
+
const GROUND = T - 12;
|
|
7
|
+
/** Stage drawers; `t` runs 0..1 from the first picture of the story to the last. */
|
|
8
|
+
const STAGES = {
|
|
9
|
+
plant(r, rng, t) {
|
|
10
|
+
const soil = hsl(28, 0.45, 0.32);
|
|
11
|
+
r.rect(6, GROUND, T - 12, 8, soil);
|
|
12
|
+
const stem = hsl(115, 0.5, 0.35);
|
|
13
|
+
if (t < 0.2) {
|
|
14
|
+
r.circle(T / 2, GROUND - 3, 5, hsl(30, 0.5, 0.45));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const h = 10 + t * 40;
|
|
18
|
+
r.stroke([[T / 2, GROUND], [T / 2 + rng.float(-1, 1), GROUND - h]], 3.2, stem);
|
|
19
|
+
const leaves = t < 0.5 ? 1 : 2;
|
|
20
|
+
for (let i = 0; i < leaves; i += 1) {
|
|
21
|
+
const y = GROUND - h * (0.35 + i * 0.3);
|
|
22
|
+
r.polygon([[T / 2, y], [T / 2 - 13, y - 7], [T / 2 - 4, y + 3]], stem).polygon([[T / 2, y], [T / 2 + 13, y - 7], [T / 2 + 4, y + 3]], stem);
|
|
23
|
+
}
|
|
24
|
+
if (t > 0.9) {
|
|
25
|
+
const top = GROUND - h;
|
|
26
|
+
const petal = hsl(rng.int(0, 360), 0.75, 0.6);
|
|
27
|
+
for (let k = 0; k < 6; k += 1) {
|
|
28
|
+
const a = (k / 6) * Math.PI * 2;
|
|
29
|
+
r.circle(T / 2 + Math.cos(a) * 7, top + Math.sin(a) * 7, 5.5, petal);
|
|
30
|
+
}
|
|
31
|
+
r.circle(T / 2, top, 4.5, hsl(48, 0.95, 0.55));
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
candle(r, rng, t) {
|
|
35
|
+
const h = 48 - t * 36;
|
|
36
|
+
const wax = hsl(rng.int(0, 360), 0.45, 0.78);
|
|
37
|
+
r.rect(T / 2 - 9, GROUND - h, 18, h, wax).rect(T / 2 - 15, GROUND, 30, 4, hsl(40, 0.2, 0.5));
|
|
38
|
+
r.stroke([[T / 2, GROUND - h], [T / 2, GROUND - h - 5]], 1.6, [40, 40, 40]);
|
|
39
|
+
r.circle(T / 2, GROUND - h - 10, 5, hsl(35, 0.95, 0.55)).polygon([[T / 2 - 4, GROUND - h - 10], [T / 2, GROUND - h - 21], [T / 2 + 4, GROUND - h - 10]], hsl(35, 0.95, 0.55));
|
|
40
|
+
r.circle(T / 2, GROUND - h - 9, 2.2, hsl(55, 1, 0.8));
|
|
41
|
+
},
|
|
42
|
+
glass(r, _rng, t) {
|
|
43
|
+
const top = 14;
|
|
44
|
+
const glass = hsl(200, 0.2, 0.55);
|
|
45
|
+
const water = hsl(205, 0.8, 0.55);
|
|
46
|
+
const level = (GROUND - top - 4) * t;
|
|
47
|
+
if (level > 0)
|
|
48
|
+
r.polygon([[T / 2 - 15, GROUND - level], [T / 2 + 15, GROUND - level], [T / 2 + 13, GROUND], [T / 2 - 13, GROUND]], water);
|
|
49
|
+
r.stroke([[T / 2 - 17, top], [T / 2 - 13, GROUND], [T / 2 + 13, GROUND], [T / 2 + 17, top]], 2.6, glass);
|
|
50
|
+
},
|
|
51
|
+
egg(r, rng, t) {
|
|
52
|
+
const shell = hsl(40, 0.4, 0.88);
|
|
53
|
+
const chick = hsl(50, 0.95, 0.58);
|
|
54
|
+
const stage = Math.round(t * 3);
|
|
55
|
+
const ring = (cx, cy, rx, ry) => Array.from({ length: 36 }, (_, i) => [cx + Math.cos((i / 36) * Math.PI * 2) * rx, cy + Math.sin((i / 36) * Math.PI * 2) * ry]);
|
|
56
|
+
if (stage <= 1) {
|
|
57
|
+
r.polygon(ring(T / 2, GROUND - 22, 16, 21), shell);
|
|
58
|
+
if (stage === 1)
|
|
59
|
+
r.stroke([[T / 2 - 14, GROUND - 26], [T / 2 - 7, GROUND - 20], [T / 2 - 1, GROUND - 28], [T / 2 + 6, GROUND - 20], [T / 2 + 14, GROUND - 26]], 2, [90, 80, 70]);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (stage === 2) {
|
|
63
|
+
r.circle(T / 2, GROUND - 30, 12, chick).circle(T / 2 + 4, GROUND - 33, 1.8, [30, 30, 30]).polygon([[T / 2 + 11, GROUND - 31], [T / 2 + 17, GROUND - 29], [T / 2 + 11, GROUND - 27]], hsl(25, 0.9, 0.5));
|
|
64
|
+
r.polygon([...ring(T / 2, GROUND - 14, 17, 14).filter(([, y]) => y >= GROUND - 16), [T / 2 - 17, GROUND - 16], [T / 2 - 9, GROUND - 22], [T / 2, GROUND - 16], [T / 2 + 9, GROUND - 22], [T / 2 + 17, GROUND - 16]], shell);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
r.circle(T / 2 - 2, GROUND - 13, 13, chick).circle(T / 2 + 6, GROUND - 31, 10, chick);
|
|
68
|
+
r.circle(T / 2 + 9, GROUND - 33, 1.8, [30, 30, 30]).polygon([[T / 2 + 15, GROUND - 32], [T / 2 + 21, GROUND - 30], [T / 2 + 15, GROUND - 28]], hsl(25, 0.9, 0.5));
|
|
69
|
+
r.polygon([[T / 2 - 22, GROUND], [T / 2 - 16, GROUND - 7], [T / 2 - 10, GROUND]], shell).polygon([[T / 2 + 12, GROUND], [T / 2 + 18, GROUND - 6], [T / 2 + 24, GROUND]], shell);
|
|
70
|
+
},
|
|
71
|
+
battery(r, _rng, t) {
|
|
72
|
+
const body = hsl(220, 0.12, 0.3);
|
|
73
|
+
r.rect(T / 2 - 22, 22, 44, 30, body).rect(T / 2 - 19, 25, 38, 24, [250, 250, 250]).rect(T / 2 + 22, 31, 5, 12, body);
|
|
74
|
+
const bars = Math.round(t * 4);
|
|
75
|
+
const fill = bars <= 1 ? hsl(5, 0.75, 0.5) : bars <= 2 ? hsl(40, 0.9, 0.5) : hsl(130, 0.6, 0.4);
|
|
76
|
+
for (let i = 0; i < bars; i += 1)
|
|
77
|
+
r.rect(T / 2 - 17 + i * 9.2, 27, 7.4, 20, fill);
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
/** Pictogram story ordering: put 3-4 pictures of a short process in the order they happen. */
|
|
81
|
+
export const story = {
|
|
82
|
+
type: 'story',
|
|
83
|
+
view: 'order',
|
|
84
|
+
minSolveMs: 1800,
|
|
85
|
+
maxAttempts: 1,
|
|
86
|
+
generate({ level, lang, rng }) {
|
|
87
|
+
const kind = rng.pick(Object.keys(STAGES));
|
|
88
|
+
const n = kind === 'egg' || level >= 1 ? 4 : 3;
|
|
89
|
+
const tiles = Array.from({ length: n }, (_, i) => {
|
|
90
|
+
const r = tileCanvas(rng);
|
|
91
|
+
STAGES[kind](r, rng, i / (n - 1));
|
|
92
|
+
return r;
|
|
93
|
+
});
|
|
94
|
+
const { solution, publicData } = orderChallenge(rng, tiles);
|
|
95
|
+
return { solution, publicData, prompt: prompt('story', lang, { story: STORIES[kind][lang] }) };
|
|
96
|
+
},
|
|
97
|
+
check(solution, answer) {
|
|
98
|
+
return checkOrder(solution.order, answer);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=story.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"story.js","sourceRoot":"","sources":["../../src/puzzles/story.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAkB,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,GAAG,EAAe,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,IAAI,EAAwC,MAAM,YAAY,CAAC;AAEpG,MAAM,CAAC,GAAG,IAAI,CAAC;AACf,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC;AAItB,oFAAoF;AACpF,MAAM,MAAM,GAA6B;IACvC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YACZ,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YACnD,OAAO;QACT,CAAC;QACD,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;QACtB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;YACxC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC9I,CAAC;QACD,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;gBAChC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;YACvE,CAAC;YACD,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7F,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5E,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9K,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,KAAK,GAAG,CAAC;YAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAC1I,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3G,CAAC;IACD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU,EAAoC,EAAE,CAChG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAU,CAAC,CAAC;QAC1I,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;YACnD,IAAI,KAAK,KAAK,CAAC;gBAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YACjL,OAAO;QACT,CAAC;QACD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACxM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAC5N,OAAO;QACT,CAAC;QACD,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;QACtF,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAClK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAClL,CAAC;IACD,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QACjC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QACrH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAChG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC;YAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACpF,CAAC;CACF,CAAC;AAEF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,KAAK,GAAiD;IACjE,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,OAAO;IACb,UAAU,EAAE,IAAI;IAChB,WAAW,EAAE,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE;QAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAgB,CAAC,CAAC;QAC1D,MAAM,CAAC,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC/C,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAClC,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IACjG,CAAC;IACD,KAAK,CAAC,QAAQ,EAAE,MAAM;QACpB,OAAO,UAAU,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PuzzleDefinition } from '../types.js';
|
|
2
|
+
import { type GridPublic, type GridSolution } from './grid.js';
|
|
3
|
+
/**
|
|
4
|
+
* Symmetry completion: the left half of a pixel picture is given (locked cells); select the cells
|
|
5
|
+
* of the right half so the picture mirrors across the dashed axis.
|
|
6
|
+
*/
|
|
7
|
+
export declare const symmetry: PuzzleDefinition<GridSolution, GridPublic>;
|
|
8
|
+
//# sourceMappingURL=symmetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symmetry.d.ts","sourceRoot":"","sources":["../../src/puzzles/symmetry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAA6C,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAM1G;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAAgB,CAAC,YAAY,EAAE,UAAU,CAgC/D,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { prompt } from '../i18n.js';
|
|
2
|
+
import { pngDataUrl } from '../render/png.js';
|
|
3
|
+
import { hsl } from '../render/raster.js';
|
|
4
|
+
import { checkGridSolution, finishGrid, gridCanvas } from './grid.js';
|
|
5
|
+
const COLS = 6;
|
|
6
|
+
const HALF = COLS / 2;
|
|
7
|
+
const CELL = 44;
|
|
8
|
+
/**
|
|
9
|
+
* Symmetry completion: the left half of a pixel picture is given (locked cells); select the cells
|
|
10
|
+
* of the right half so the picture mirrors across the dashed axis.
|
|
11
|
+
*/
|
|
12
|
+
export const symmetry = {
|
|
13
|
+
type: 'symmetry',
|
|
14
|
+
view: 'grid',
|
|
15
|
+
minSolveMs: 2000,
|
|
16
|
+
maxAttempts: 1,
|
|
17
|
+
generate({ level, lang, rng }) {
|
|
18
|
+
const rows = level >= 1 ? 5 : 4;
|
|
19
|
+
const n = rows * COLS;
|
|
20
|
+
let filled = [];
|
|
21
|
+
while (filled.length < 3 || filled.length > rows * 2) {
|
|
22
|
+
filled = [];
|
|
23
|
+
for (let r = 0; r < rows; r += 1)
|
|
24
|
+
for (let c = 0; c < HALF; c += 1)
|
|
25
|
+
if (rng.next() < 0.42)
|
|
26
|
+
filled.push(r * COLS + c);
|
|
27
|
+
}
|
|
28
|
+
const cells = filled.map((i) => Math.floor(i / COLS) * COLS + (COLS - 1 - (i % COLS))).sort((a, b) => a - b);
|
|
29
|
+
const locked = Array.from({ length: n }, (_, i) => i).filter((i) => i % COLS < HALF);
|
|
30
|
+
const g = gridCanvas(rng, rows, COLS, CELL);
|
|
31
|
+
const color = hsl(rng.int(0, 360), 0.6, 0.45);
|
|
32
|
+
g.r.rect(0, 0, HALF * CELL, rows * CELL, [255, 255, 255], 70);
|
|
33
|
+
for (const i of filled) {
|
|
34
|
+
const [x, y] = g.center(i);
|
|
35
|
+
g.r.rect(x - CELL / 2 + 4, y - CELL / 2 + 4, CELL - 8, CELL - 8, color);
|
|
36
|
+
}
|
|
37
|
+
finishGrid(g, rows, COLS);
|
|
38
|
+
const axis = hsl(rng.int(0, 360), 0.5, 0.35);
|
|
39
|
+
for (let y = 2; y < rows * CELL; y += 12)
|
|
40
|
+
g.r.rect(HALF * CELL - 1.5, y, 3, 7, axis);
|
|
41
|
+
return {
|
|
42
|
+
solution: { cells, n },
|
|
43
|
+
prompt: prompt('symmetry', lang),
|
|
44
|
+
publicData: { image: pngDataUrl(g.r.finish().noise(6, rng)), width: g.width, height: g.height, rows, cols: COLS, gridTop: 0, select: 'many', locked },
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
check: checkGridSolution,
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=symmetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symmetry.js","sourceRoot":"","sources":["../../src/puzzles/symmetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Pt, type Raster } from '../render/raster.js';
|
|
2
|
+
import type { Rng } from '../rng.js';
|
|
3
|
+
import type { PuzzleDefinition } from '../types.js';
|
|
4
|
+
export interface TapsSolution {
|
|
5
|
+
/** Tap targets in the required order. */
|
|
6
|
+
readonly targets: readonly Pt[];
|
|
7
|
+
}
|
|
8
|
+
/** View `taps`: tap points on one picture in a required order (`count` taps). */
|
|
9
|
+
export interface TapsPublic {
|
|
10
|
+
readonly image: string;
|
|
11
|
+
readonly width: number;
|
|
12
|
+
readonly height: number;
|
|
13
|
+
readonly count: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const TAP_RADIUS = 22;
|
|
16
|
+
/** A labelled bubble (shared by tap-order and spell). */
|
|
17
|
+
export declare function bubble(r: Raster, rng: Rng, label: string, cx: number, cy: number, radius: number): void;
|
|
18
|
+
/** Tap the numbers in ascending order. Positions exist only in the PNG. */
|
|
19
|
+
export declare const tapOrder: PuzzleDefinition<TapsSolution, TapsPublic>;
|
|
20
|
+
//# sourceMappingURL=tap-order.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap-order.d.ts","sourceRoot":"","sources":["../../src/puzzles/tap-order.ts"],"names":[],"mappings":"AAEA,OAAO,EAAO,KAAK,EAAE,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,MAAM,WAAW,YAAY;IAC3B,yCAAyC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC;CACjC;AAED,iFAAiF;AACjF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,UAAU,KAAK,CAAC;AAE7B,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAIvG;AAKD,2EAA2E;AAC3E,eAAO,MAAM,QAAQ,EAAE,gBAAgB,CAAC,YAAY,EAAE,UAAU,CAqB/D,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { prompt } from '../i18n.js';
|
|
2
|
+
import { pngDataUrl } from '../render/png.js';
|
|
3
|
+
import { hsl } from '../render/raster.js';
|
|
4
|
+
import { checkTaps, clutter, drawText, roundPt, scatter, softBackground } from './common.js';
|
|
5
|
+
export const TAP_RADIUS = 22;
|
|
6
|
+
/** A labelled bubble (shared by tap-order and spell). */
|
|
7
|
+
export function bubble(r, rng, label, cx, cy, radius) {
|
|
8
|
+
const fill = hsl(rng.int(0, 360), 0.55, 0.9);
|
|
9
|
+
r.circle(cx, cy, radius + 2, hsl(rng.int(0, 360), 0.4, 0.45)).circle(cx, cy, radius, fill);
|
|
10
|
+
drawText(r, rng, label, cx, cy, label.length > 1 ? radius * 0.85 : radius, hsl(rng.int(0, 360), 0.6, 0.28), { tilt: 12, halo: fill });
|
|
11
|
+
}
|
|
12
|
+
const W = 300;
|
|
13
|
+
const H = 190;
|
|
14
|
+
/** Tap the numbers in ascending order. Positions exist only in the PNG. */
|
|
15
|
+
export const tapOrder = {
|
|
16
|
+
type: 'tap-order',
|
|
17
|
+
view: 'taps',
|
|
18
|
+
minSolveMs: 1500,
|
|
19
|
+
maxAttempts: 2,
|
|
20
|
+
generate({ level, lang, rng }) {
|
|
21
|
+
const count = level >= 2 ? 5 : 4;
|
|
22
|
+
const values = rng.sample(Array.from({ length: level >= 1 ? 49 : 19 }, (_, i) => i + 1), count).sort((a, b) => a - b);
|
|
23
|
+
const r = softBackground(rng, W, H);
|
|
24
|
+
clutter(r, rng, 0, 0, W, H, 8);
|
|
25
|
+
const spots = scatter(rng, count, { x0: 30, y0: 30, x1: W - 30, y1: H - 30 }, 62);
|
|
26
|
+
values.forEach((v, i) => bubble(r, rng, String(v), spots[i][0], spots[i][1], 22));
|
|
27
|
+
return {
|
|
28
|
+
solution: { targets: spots.map(roundPt) },
|
|
29
|
+
prompt: prompt('tapOrder', lang),
|
|
30
|
+
publicData: { image: pngDataUrl(r.finish().noise(8, rng)), width: W, height: H, count },
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
check(solution, answer) {
|
|
34
|
+
return checkTaps(solution.targets, answer, { w: W, h: H }, TAP_RADIUS + 4);
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=tap-order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap-order.js","sourceRoot":"","sources":["../../src/puzzles/tap-order.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PuzzleDefinition } from '../types.js';
|
|
2
|
+
import { type PathPublic, type TraceSolution } from './trace.js';
|
|
3
|
+
/** Connect-the-dots variant: dots labelled A, B, C… joined in alphabetical order. */
|
|
4
|
+
export declare const traceLetters: PuzzleDefinition<TraceSolution, PathPublic>;
|
|
5
|
+
//# sourceMappingURL=trace-letters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-letters.d.ts","sourceRoot":"","sources":["../../src/puzzles/trace-letters.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAA6B,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAE5F,qFAAqF;AACrF,eAAO,MAAM,YAAY,EAAE,gBAAgB,CAAC,aAAa,EAAE,UAAU,CAcpE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { prompt } from '../i18n.js';
|
|
2
|
+
import { checkConnect, connectDots } from './trace.js';
|
|
3
|
+
/** Connect-the-dots variant: dots labelled A, B, C… joined in alphabetical order. */
|
|
4
|
+
export const traceLetters = {
|
|
5
|
+
type: 'trace-letters',
|
|
6
|
+
view: 'path',
|
|
7
|
+
minSolveMs: 900,
|
|
8
|
+
maxAttempts: 2,
|
|
9
|
+
generate({ level, lang, rng }) {
|
|
10
|
+
const count = level >= 2 ? 5 : 4;
|
|
11
|
+
const labels = 'ABCDE'.slice(0, count).split('');
|
|
12
|
+
const { dots, image } = connectDots(rng, labels, level >= 1 ? 3 : 2);
|
|
13
|
+
return { solution: { dots }, prompt: prompt('traceLetters', lang, { last: labels[count - 1] }), publicData: { image, width: 300, height: 200, count } };
|
|
14
|
+
},
|
|
15
|
+
check(solution, answer) {
|
|
16
|
+
return checkConnect(solution.dots, answer);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=trace-letters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-letters.js","sourceRoot":"","sources":["../../src/puzzles/trace-letters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAuC,MAAM,YAAY,CAAC;AAE5F,qFAAqF;AACrF,MAAM,CAAC,MAAM,YAAY,GAAgD;IACvE,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,GAAG;IACf,WAAW,EAAE,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE;QAC3B,MAAM,KAAK,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,OAAO,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAE,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC;IAC3J,CAAC;IACD,KAAK,CAAC,QAAQ,EAAE,MAAM;QACpB,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type Pt } from '../render/raster.js';
|
|
2
|
+
import type { Rng } from '../rng.js';
|
|
3
|
+
import { type CheckResult, type PuzzleDefinition } from '../types.js';
|
|
4
|
+
export interface TraceSolution {
|
|
5
|
+
readonly dots: readonly Pt[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* View `path`: draw on a picture (pointer) or place points with a keyboard crosshair. With `grid`
|
|
9
|
+
* the keyboard moves cell by cell (mazes).
|
|
10
|
+
*/
|
|
11
|
+
export interface PathPublic {
|
|
12
|
+
readonly image: string;
|
|
13
|
+
readonly width: number;
|
|
14
|
+
readonly height: number;
|
|
15
|
+
readonly count?: number;
|
|
16
|
+
readonly grid?: {
|
|
17
|
+
readonly cols: number;
|
|
18
|
+
readonly rows: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Shared connect-the-dots generator; `labels` are drawn next to the dots in order. */
|
|
22
|
+
export declare function connectDots(rng: Rng, labels: readonly string[], decoyCount: number): {
|
|
23
|
+
dots: Pt[];
|
|
24
|
+
image: string;
|
|
25
|
+
};
|
|
26
|
+
/** Checks that the path visits the dots in order without sweeping the canvas. */
|
|
27
|
+
export declare function checkConnect(dots: readonly Pt[], answer: unknown): CheckResult;
|
|
28
|
+
/** Connect numbered dots in order (unnumbered decoys are present). */
|
|
29
|
+
export declare const trace: PuzzleDefinition<TraceSolution, PathPublic>;
|
|
30
|
+
/** @deprecated alias of {@link PathPublic}. */
|
|
31
|
+
export type TracePublic = PathPublic;
|
|
32
|
+
//# sourceMappingURL=trace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../../src/puzzles/trace.ts"],"names":[],"mappings":"AAIA,OAAO,EAAO,KAAK,EAAE,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAsB,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG1F,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAClE;AAaD,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAiBlH;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,GAAG,WAAW,CAmB9E;AAED,sEAAsE;AACtE,eAAO,MAAM,KAAK,EAAE,gBAAgB,CAAC,aAAa,EAAE,UAAU,CAa7D,CAAC;AAEF,+CAA+C;AAC/C,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { analyzeTrajectory, parseInteraction } from '../heuristics.js';
|
|
2
|
+
import { prompt } from '../i18n.js';
|
|
3
|
+
import { glyphStrokes } from '../render/glyphs.js';
|
|
4
|
+
import { pngDataUrl } from '../render/png.js';
|
|
5
|
+
import { hsl } from '../render/raster.js';
|
|
6
|
+
import { invalid, ok, wrong } from '../types.js';
|
|
7
|
+
import { isRecord, roundPt, scatter, scenicBackground } from './common.js';
|
|
8
|
+
const W = 300;
|
|
9
|
+
const H = 200;
|
|
10
|
+
const HIT_RADIUS = 20;
|
|
11
|
+
const MARGIN = 26;
|
|
12
|
+
function pathLength(points) {
|
|
13
|
+
let len = 0;
|
|
14
|
+
for (let i = 1; i < points.length; i += 1)
|
|
15
|
+
len += Math.hypot(points[i][0] - points[i - 1][0], points[i][1] - points[i - 1][1]);
|
|
16
|
+
return len;
|
|
17
|
+
}
|
|
18
|
+
/** Shared connect-the-dots generator; `labels` are drawn next to the dots in order. */
|
|
19
|
+
export function connectDots(rng, labels, decoyCount) {
|
|
20
|
+
const dots = scatter(rng, labels.length, { x0: MARGIN, y0: MARGIN, x1: W - MARGIN, y1: H - MARGIN }, 62);
|
|
21
|
+
const decoys = scatter(rng, decoyCount, { x0: MARGIN, y0: MARGIN, x1: W - MARGIN, y1: H - MARGIN }, 44, dots);
|
|
22
|
+
const r = scenicBackground(rng, W, H, 10);
|
|
23
|
+
r.rect(0, 0, W, H, [255, 255, 255], 120);
|
|
24
|
+
const dotColor = hsl(rng.int(0, 360), 0.65, 0.35);
|
|
25
|
+
for (const [x, y] of [...dots, ...decoys])
|
|
26
|
+
r.circle(x, y, 8, [255, 255, 255]).circle(x, y, 6, dotColor);
|
|
27
|
+
dots.forEach(([x, y], i) => {
|
|
28
|
+
const angle = rng.float(0, Math.PI * 2);
|
|
29
|
+
const lx = Math.min(W - 10, Math.max(10, x + Math.cos(angle) * 17));
|
|
30
|
+
const ly = Math.min(H - 12, Math.max(12, y + Math.sin(angle) * 17));
|
|
31
|
+
for (const stroke of glyphStrokes(labels[i], { x: lx, y: ly, size: 15, rotateDeg: rng.float(-15, 15), jitter: 0.6 }, () => rng.next())) {
|
|
32
|
+
r.stroke(stroke, 4.4, [255, 255, 255]);
|
|
33
|
+
r.stroke(stroke, 2.2, dotColor);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return { dots: dots.map(roundPt), image: pngDataUrl(r.finish().noise(8, rng)) };
|
|
37
|
+
}
|
|
38
|
+
/** Checks that the path visits the dots in order without sweeping the canvas. */
|
|
39
|
+
export function checkConnect(dots, answer) {
|
|
40
|
+
if (!isRecord(answer))
|
|
41
|
+
return invalid('answer');
|
|
42
|
+
const interaction = parseInteraction(answer['interaction'], { w: W, h: H });
|
|
43
|
+
if (!interaction || interaction.trail.length < 2)
|
|
44
|
+
return invalid('interaction');
|
|
45
|
+
const points = interaction.trail;
|
|
46
|
+
// The dots must be visited as an ordered subsequence of the path. Brushing past a later dot
|
|
47
|
+
// on the way is allowed (people do that); sweeping is prevented by the length bound below.
|
|
48
|
+
let next = 0;
|
|
49
|
+
for (const [x, y] of points) {
|
|
50
|
+
const target = dots[next];
|
|
51
|
+
if (target && Math.hypot(target[0] - x, target[1] - y) <= HIT_RADIUS)
|
|
52
|
+
next += 1;
|
|
53
|
+
if (next === dots.length)
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
if (next !== dots.length)
|
|
57
|
+
return wrong('incomplete');
|
|
58
|
+
// Refuse "lawn-mower" sweeps: the path may wander, but not cover the whole canvas.
|
|
59
|
+
if (pathLength(points) > pathLength(dots) * 2.2 + 160)
|
|
60
|
+
return wrong('path-too-long');
|
|
61
|
+
if (interaction.mode === 'keyboard' && points.length > 40)
|
|
62
|
+
return invalid('too-many-keyboard-points');
|
|
63
|
+
const verdict = analyzeTrajectory(interaction, { axis: 'free', minDurationMs: 300 });
|
|
64
|
+
return verdict.human ? ok : { ok: false, reason: 'bot-suspected', detail: verdict.reasons.join(',') };
|
|
65
|
+
}
|
|
66
|
+
/** Connect numbered dots in order (unnumbered decoys are present). */
|
|
67
|
+
export const trace = {
|
|
68
|
+
type: 'trace',
|
|
69
|
+
view: 'path',
|
|
70
|
+
minSolveMs: 900,
|
|
71
|
+
maxAttempts: 2,
|
|
72
|
+
generate({ level, lang, rng }) {
|
|
73
|
+
const count = level >= 2 ? 5 : 4;
|
|
74
|
+
const { dots, image } = connectDots(rng, Array.from({ length: count }, (_, i) => String(i + 1)), level >= 1 ? 3 : 2);
|
|
75
|
+
return { solution: { dots }, prompt: prompt('trace', lang, { n: count }), publicData: { image, width: W, height: H, count } };
|
|
76
|
+
},
|
|
77
|
+
check(solution, answer) {
|
|
78
|
+
return checkConnect(solution.dots, answer);
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=trace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/puzzles/trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Rng } from '../rng.js';
|
|
2
|
+
export declare const SAMPLE_RATE = 11025;
|
|
3
|
+
/** Mono float buffer in [-1, 1] at {@link SAMPLE_RATE}. */
|
|
4
|
+
export declare class Track {
|
|
5
|
+
readonly length: number;
|
|
6
|
+
readonly data: Float32Array;
|
|
7
|
+
constructor(length: number);
|
|
8
|
+
static ms(ms: number): Track;
|
|
9
|
+
get durationMs(): number;
|
|
10
|
+
/** Mixes `src` in at `atMs` with gain `g`. */
|
|
11
|
+
mix(src: Float32Array, atMs: number, g?: number): this;
|
|
12
|
+
}
|
|
13
|
+
/** xorshift128+ style generator seeded from the puzzle Rng (fast per-sample noise). */
|
|
14
|
+
export declare function noiseSource(rng: Rng): () => number;
|
|
15
|
+
/** A soft sine "beep" with a few harmonics and a short attack/release. */
|
|
16
|
+
export declare function beep(freq: number, ms: number, rnd: () => number): Float32Array;
|
|
17
|
+
/** Brown-ish background noise with a slow amplitude wobble (rain/room tone). */
|
|
18
|
+
export declare function backgroundNoise(track: Track, level: number, rnd: () => number): void;
|
|
19
|
+
type F3 = readonly [number, number, number];
|
|
20
|
+
export interface Phone {
|
|
21
|
+
/** Formant targets at the start and end of the segment (diphthongs glide between them). */
|
|
22
|
+
readonly f: F3;
|
|
23
|
+
readonly f2?: F3;
|
|
24
|
+
readonly ms: number;
|
|
25
|
+
/** Voicing amplitude 0..1. */
|
|
26
|
+
readonly av: number;
|
|
27
|
+
/** Frication amplitude 0..1 and its resonance. */
|
|
28
|
+
readonly af?: number;
|
|
29
|
+
readonly fc?: number;
|
|
30
|
+
readonly fbw?: number;
|
|
31
|
+
/** Aspiration (breathy noise through the formants). */
|
|
32
|
+
readonly ah?: number;
|
|
33
|
+
}
|
|
34
|
+
export interface Voice {
|
|
35
|
+
/** Base pitch in Hz. */
|
|
36
|
+
readonly f0: number;
|
|
37
|
+
/** Formant scale (vocal tract length): ~0.9 deep .. 1.15 bright. */
|
|
38
|
+
readonly scale: number;
|
|
39
|
+
/** Speaking-rate multiplier for durations. */
|
|
40
|
+
readonly rate: number;
|
|
41
|
+
}
|
|
42
|
+
/** Synthesizes one English digit word. Returns normalized float samples. */
|
|
43
|
+
export declare function speakDigit(digit: number, voice: Voice, rnd: () => number): Float32Array;
|
|
44
|
+
/** Synthesizes a phone sequence (exported for tuning tools). */
|
|
45
|
+
export declare function speakPhones(phones: readonly Phone[], voice: Voice, rnd: () => number): Float32Array;
|
|
46
|
+
/** Muffled vowel "babble" fragments (a distant crowd) to frustrate off-the-shelf recognisers. */
|
|
47
|
+
export declare function babble(track: Track, level: number, rnd: () => number, count: number): void;
|
|
48
|
+
/** Peak-normalizes to `peak` and applies tiny fades at both ends. */
|
|
49
|
+
export declare function master(track: Track, peak?: number): Track;
|
|
50
|
+
/** Encodes as a canonical 44-byte-header PCM WAV (mono, 16-bit, {@link SAMPLE_RATE}). */
|
|
51
|
+
export declare function encodeWav(track: Track): Uint8Array;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=audio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../../src/render/audio.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAErC,eAAO,MAAM,WAAW,QAAS,CAAC;AAElC,2DAA2D;AAC3D,qBAAa,KAAK;IAEJ,QAAQ,CAAC,MAAM,EAAE,MAAM;IADnC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;gBACP,MAAM,EAAE,MAAM;IAGnC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,KAAK;IAG5B,IAAI,UAAU,IAAI,MAAM,CAEvB;IACD,8CAA8C;IAC9C,GAAG,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,SAAI,GAAG,IAAI;CAKlD;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,MAAM,CAelD;AAsBD,0EAA0E;AAC1E,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,YAAY,CAY9E;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,IAAI,CAQpF;AAID,KAAK,EAAE,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE5C,MAAM,WAAW,KAAK;IACpB,2FAA2F;IAC3F,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACtB;AA6BD,MAAM,WAAW,KAAK;IACpB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,4EAA4E;AAC5E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,YAAY,CAIvF;AAED,gEAAgE;AAChE,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,YAAY,CA6DnG;AAED,iGAAiG;AACjG,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAa1F;AAED,qEAAqE;AACrE,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,SAAO,GAAG,KAAK,CAUvD;AAED,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAsBlD"}
|