ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A kids' phonics practice web app — a companion for a homeschool reading program. Pip the pond frog hosts 25-round games; kids tap a speaker to hear a word, then answer, and earn stars saved in the browser (localStorage). The reader's name (shown in the greeting and end screens) is editable in the grown-ups settings panel.README 전문 보기 ↗A kids' phonics practice web app — a companion for a homeschool reading program. Pip the pond frog hosts 25-round games; kids tap a speaker to hear a word, then answer, and earn stars saved in the browser (localStorage). The reader's name (shown in the greeting and end screens) is editable in the grown-ups settings panel.
The game controller draws each round's question without replacement from a shuffled copy of the pool, built fresh every time a lesson/game launches or "Play again" is tapped — so a single sitting never asks the same question twice. Multiple-choice distractors are also deduped so the 3 options shown in any one round are always distinct from each other (they can still recur across different rounds — that's normal). Because of this, every pool in lessons.js needs at least as many unique items as the rounds drawn from it: 25 for a single-stage lesson/game, or at least each stage's rounds count for a multi-stage lesson. resolveOrder() in app.js handles the shuffling; if a pool you add is smaller than the rounds needed, that stage will just quietly loop through fewer unique questions rather than crash — grow the pool if you want a full 25.
Sight Word Flash works differently — see the sightword row below.
word-pond/
index.html ← page shell, links styles.css, loads lessons.js then app.js
styles.css ← all visual styling
app.js ← speech helper, save/load, menu rendering, game engines, game controller
lessons.js ← word data + LESSONS and GAMES arrays ← edit THIS to add content
README.md ← this file
Everything is a static site — no build step, no server required. Open index.html directly, or deploy it anywhere that serves static files (Vercel, Netlify, GitHub Pages, etc.).
Open lessons.js. At the bottom of the word-data section there's a LESSONS array. Add one object per lesson:
let LESSONS=[
{id:'L1', n:1, title:'Open & Closed Syllables', emoji:'🚪', cls:'c-review', engine:'syllabletype', pool:OPENCLOSED},
{id:'L2', n:2, title:'Your New Topic', emoji:'✨', cls:'c-magic', engine:'magic', pool:MAGIC}
];
Fields:
| Field | What it is |
|---|---|
id | Unique string, e.g. 'L2' |
n | Lesson number shown on the card (Lesson 2) |
title | Title shown on the card |
emoji | One emoji shown on the card |
cls | Card color class — reuse one of: c-review, c-syll, c-sound, c-ed, c-magic, c-contr, c-phon |
engine | Which game engine runs this lesson (see below) |
pool | The word data the engine draws from |
| Engine | Pool shape | Example |
|---|---|---|
review | flat array of words, e.g. ['cat','dog','run'] | REVIEW |
phonogram | {focus:['ee','ar'], all: PHONOGRAMS} — focus limits which sounds are quizzed; omit focus to use every key in all | PHONOGRAMS, CONSPHON |
magic | array of {short, long, v, mean} (silent-e word pairs) | MAGIC |
ed | object keyed by sound, e.g. {'/t/':[...], '/d/':[...], '/id/':[...]} | ED |
contraction | array of {two, one} pairs | CONTRACTIONS |
syllabletype | array of {w, t} where t is 'open' or 'closed' | OPENCLOSED |
syllabletag | array of {w, t} where t is 'open', 'closed', 'name' (vowel-consonant-e), 'team' (vowel team) or 'bossy' (a vowel with an r after it). The buttons shown are derived from the types the pool actually uses, so a three-type pool asks a three-way question and a five-type pool asks a five-way one; three buttons sit in one row, five wrap 2+2+1 with the last spanning the row. Each option carries its definition as a caption, since the child is learning the tags themselves | SYLTAG15, SYLTAG25, SYLTAG31 |
syllable | array of {w, n} where n is syllable count | SYLLABLES |
wordchange | array of {from, to} pairs, OR {instruction, pairs:[{from,to}]} to customize the prompt text. Any pair may add say — a spoken respelling used instead of from for the audio (see "Making the voice say it right"). A pair may also add hint, a short line shown under the word — use it whenever the prompt alone would leave more than one option correct |
A lesson stage may also use sightword to have a word list read aloud rather than answered — Lesson 14 uses it for the Word Cards. Only the standalone Sight Word Flash game records lifetime mastery, so a lesson borrowing the engine never writes into the saved mastery set.
Two games drill until every word is known rather than running 25 rounds: Sight Word Flash and Leap Words. The MASTERY table in app.js describes both, and each keeps its own saved set, so progress in one never counts toward the other. Saves written before Leap Words existed still load: a bare mastered array is read as the sight-word set.
sightword is special-cased in the game controller (by the sight game id) to track long-term mastery rather than just session rounds: every word marked "I read it!" is saved to localStorage permanently, the header shows "N / total left to master" instead of a round counter, and mastered words drop out of the rotation so practice always focuses on what's left. Marking the last word triggers a full-screen congratulations achievement. "Reset stars & progress" in settings clears mastery too.
Browser text-to-speech pronounces whole dictionary words well and bare fragments badly. Given a
piece of a word it falls back to letter-to-sound rules, which routinely produces the wrong vowel:
"ro" from robot comes out with a short o ("rah"), the exact opposite of the long o an open
syllable is supposed to teach. Two rules follow from this:
speak(). This bit the phonogram engine (it used to speak the
bare grapheme "nk"; it now speaks a real word from that sound family) and then the
wordchange engine's syllable pairs.say. A wordchange pair shows from and
speaks say when present, so the child reads ro...bot but hears syllables respelled as words
the voice already knows: say:'roe, bot'. The comma adds a short pause between the parts.Respellings that work for open (long-vowel) syllables: oh ee bee zee pree dee (long e/o),
roe moe bro fro pro toe (long o), sigh pie tie fie eye (long i),
bay pay (long a), stew hue mew (long u). Also respell a closed syllable whose spelling
is itself a word with a different sound — gin reads as the drink, so begin uses ghin.
Closed syllables need care too when they are unstressed: a bare et is read as a long e, so pocket uses say:'pock, ett'. And a syllable whose spelling implies a soft c needs a k — cricket uses krick.
There is no way to unit-test pronunciation; it has to be listened to. After adding say values,
play the lesson once with sound on and check each new word.
A lesson can also run more than one activity back to back, and show a teaching screen before practice starts. Use stages instead of engine/pool:
{id:'L4', n:4, title:'The Four Sounds of Y', emoji:'🔤', cls:'c-magic',
intro:{
topic:'Phonogram Y — four sounds, one letter',
lines:['One or more paragraphs of teaching text. <b>Bold</b> is allowed.'],
words:['yarn','gym','my','happy'], // optional tap-to-hear example chips
review:['by','fly','try','cry'], // optional plain-text word list
trick:{title:'Tricky word: from', points:[{w:'from', note:'the o says "uh", not its usual short o sound'}]} // optional callout
},
stages:[
{engine:'review', pool:YWORDS, rounds:6, label:'Find the Y Word'},
{engine:'wordchange', pool:{instruction:'Custom prompt text', pairs:YCHANGE}, rounds:4, label:'Change the Word'}
]
}
stages round counts should add up to 25 to keep pacing and the star-reward math (a perfect run earns 2 bonus stars) consistent with every other lesson and game. intro is optional — omit it and use engine/pool directly (like L1) for a lesson that jumps straight into practice.
To add brand-new words, either extend an existing data array at the top of lessons.js, or declare a new const and point a lesson's pool at it (for phonogram, wrap it as {all: YOUR_NEW_OBJECT}).
All practice words are original/generic phonics content — do not paste in copyrighted curriculum text. If you're matching a Teacher's Manual lesson, describe the skill and words in your own words/list, not verbatim text from the manual.
The GAMES array (also in lessons.js) is the "Extra Practice" section — general skill-practice games a grown-up can toggle on/off from the settings panel. Same shape as LESSONS plus sub (subtitle), on (default enabled), and hint (shown in settings).
The reader's name is stored in childName (app.js), defaults to 'Mckenna', and is editable via the "Reader's name" field in the grown-ups settings panel — it persists to localStorage and appears in the home greeting, the end-of-session screen, and the sight-word mastery achievement screen.
Pip the frog (pipSVG(size) in app.js) appears in the header (always visible), the lesson-intro screen, the game screen's top bar, the settings panel header, the end-of-session screen, and the achievement screen. Every Pip on screen bounces together whenever a star is earned (addStar() targets every .mascot element, not just one).
Just open index.html in a browser — no build step needed. Note: some browsers block localStorage when a file is opened directly (file://) instead of served over http(s)://; stars still work during the session but won't persist. To test persistence locally, serve the folder, e.g.:
npx serve .
This repo auto-deploys to Vercel on every push to main. To add Lesson 2 or 3:
lessons.js — add the lesson object and any new word data.WORDCHANGE, YCHANGE, GUESSWORDS, GUESS10 |
syllablesplit | array of {w, parts:[p1,p2]} — student picks the correctly hyphenated split (e.g. "pic-nic"); wrong-split distractors are generated automatically | SPLIT |
vcvsplit | array of {w, open, closed, correct} — one VCV word with BOTH plausible splits: open sends the middle consonant to the second syllable (open first syllable, long vowel), closed slides it back to the first (closed first syllable, short vowel), and correct is 'open' or 'closed'. Exactly two options are shown, so the wrong answer is always the specific mistake the rule corrects rather than an invented split | VCV12 |
minimalpair | array of {w, other} — w is spoken and is the answer, other is the word it contrasts with. Two options, nothing shown until the answer, so the child has to hear the difference rather than read it. Alternate which member is the target so one side is never the safe guess | SILENTE14 |
sortsound | {instruction, buckets:[{key, ex, why}], items:[{w, k}]} — a "which sound do you hear?" sort, generic over its buckets (unlike ed, whose three are fixed). Two buckets sit side by side, three fill the row. k names the bucket a word belongs in; why is the explanation shown in feedback | LONGU17, GOLDSORT29, EJOBS44 |
heteronym | array of {sentence, word, right, wrong, note} — the sentence carries the target word in <b> tags and the child picks which meaning it has here. The only engine that never speaks: saying the sentence would give the answer away, and browser speech guesses heteronyms in context unreliably | HETERO21 |
expand | array of {two, one} — the mirror of contraction: shows the contraction and the child picks the two words it stands for. Same pool shape, so one pool feeds both directions | CONTRACT27 |
syllablesplit3 | array of {w, parts:[p1,p2,p3]} — three-syllable words. Wrong options carry two splits as well, just in the wrong places, so hyphen-counting cannot substitute for deciding where the syllables break. Every generated piece is at least two letters | THREESYL33 |
leapword | array of {w, n, why, breaker} — like sightword, but after answering it names the lesson the word came from and why it is odd. breaker marks a true rule breaker as against a word that merely arrives before the rule explaining it | LEAPWORDS |
sightword | flat word array — no multiple choice; the word is shown, the child reads it aloud, and self-reports "I read it!" or "Still tricky" (only the former earns a star) | SIGHTWORDS |