Spaces:
Running
Running
| /** | |
| * 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; | |