Spaces:
Running
Running
File size: 2,275 Bytes
843a4b2 d96c9a7 843a4b2 d96c9a7 843a4b2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | /**
* Learn view: the letter ↔ rhythm chart. Tap any entry to hear (or have the
* robot tap) its rhythm — the whole point is that a letter *is* a rhythm.
*/
import { el, clear, morsePattern } from "./dom.js";
import { CHAR_TO_MORSE, morseToTokens } from "../lib/morse.js";
import { tokensToOnsets } from "../lib/wire.js";
const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
const DIGITS = "0123456789".split("");
export function createLearn(ctx) {
const root = el("section.view#view-learn");
function playChar(ch) {
const pattern = CHAR_TO_MORSE[ch];
if (!pattern) return;
const onsets = tokensToOnsets(morseToTokens(pattern), ctx.timing());
if (ctx.state.emitter === "robot" && ctx.reachy) {
ctx.tapper().tap(onsets);
} else {
ctx.synth().play(onsets, { clickMs: ctx.timing().clickMs });
}
}
function grid(title, chars) {
const g = el("div.chart-grid");
chars.forEach((ch) => {
const cell = el("button.chart-cell", { onclick: () => {
playChar(ch);
cell.classList.remove("ping"); void cell.offsetWidth; cell.classList.add("ping");
} }, [
el("span.cell-char", {}, ch),
morsePattern(CHAR_TO_MORSE[ch]),
]);
g.append(cell);
});
return el("div.chart-section", {}, [el("h3", {}, title), g]);
}
const emitterNote = el("div.status muted");
function refresh() {
emitterNote.textContent = ctx.state.emitter === "robot" && ctx.reachy
? "Tapping plays on the robot's antennas."
: "Tapping plays a beep on this device. (Switch sender in Compose.)";
}
root.append(
el("h2", {}, "Learn Morse"),
el("p.muted", {}, "A letter is just a rhythm of short and long beats. Tap any tile to feel it."),
emitterNote,
grid("Letters", LETTERS),
grid("Numbers", DIGITS),
el("div.legend", {}, [
el("span.legend-item", {}, [morsePattern("."), " dot: one tap"]),
el("span.legend-item", {}, [morsePattern("-"), " dash: quick double tap"]),
]),
);
refresh();
return { node: root, onShow: refresh };
}
void clear;
|