{"id":50948561,"url":"https://github.com/oduerr/hsk","last_synced_at":"2026-06-17T23:02:33.006Z","repository":{"id":309695581,"uuid":"1037151265","full_name":"oduerr/hsk","owner":"oduerr","description":"HSK Flashcard Game","archived":false,"fork":false,"pushed_at":"2025-08-20T09:56:31.000Z","size":31308,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-20T11:45:33.808Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oduerr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-13T06:27:15.000Z","updated_at":"2025-08-20T09:56:34.000Z","dependencies_parsed_at":"2025-08-13T10:26:47.488Z","dependency_job_id":"af03f62c-4538-4713-9010-c4544c405669","html_url":"https://github.com/oduerr/hsk","commit_stats":null,"previous_names":["oduerr/hsk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/oduerr/hsk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oduerr%2Fhsk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oduerr%2Fhsk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oduerr%2Fhsk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oduerr%2Fhsk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oduerr","download_url":"https://codeload.github.com/oduerr/hsk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oduerr%2Fhsk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34468766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-17T23:02:32.141Z","updated_at":"2026-06-17T23:02:32.998Z","avatar_url":"https://github.com/oduerr.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HSK Flashcards (Offline HTML/JS)\n\n## Disclaimer\n\nThis is a work in progress! Probably too much have been done with AI coding Agents.\nThe Data Model is quite patchy, it (kind of) works but before adding new features to the Data Model a thorough review is needed\n\n_This is an experimental learning project; it stores all data locally in your browser and uses some third-party APIs (see [Privacy](#privacy))._\n\n## Quick start\n\n- Open `index.html` in a modern browser.\n- If your browser blocks `file://` fetch for CSV, run a tiny server from the `hsk/` folder:\n  - macOS/Linux: `python3 -m http.server`\n\n## Data \u0026 levels\n\n- CSV format: `hanzi,pinyin,english,locale` (UTF‑8, quoted fields supported; pinyin spacing normalized; locale defaults to zh-CN if missing).\n- Vocabulary files live in `data/` directory.\n- The app automatically discovers available vocabulary files using a smart discovery system.\n\n## File Loading\n\n### Primary Method: `vocab.csv` Index\nThe app primarily discovers vocabulary files by reading `data/vocab.csv`, which serves as a central index:\n\n```csv\nfilename,display_name,description\nhsk1.csv,HSK 1,Basic Chinese vocabulary (150 words)\nhsk2.csv,HSK 2,Elementary Chinese vocabulary (300 words)\neng_oliver.csv,Oliver's English,Personal English vocabulary collection\n```\n\n**To add new vocabulary files:**\n1. Place your CSV file in the `data/` folder\n2. Add a row to `data/vocab.csv` with:\n   - `filename`: The actual CSV filename\n   - `display_name`: User-friendly name shown in the interface\n   - `description`: Optional description of the content\n3. Reload the page - the file will automatically appear in the vocabulary manager\n\n### Fallback Discovery\nIf `vocab.csv` is not available, the app falls back to pattern-based discovery, automatically detecting common filename patterns like `hsk*.csv`, `vocabulary.csv`, etc.\n\n### Benefits of `vocab.csv` Approach\n- **User control**: You decide what files are available\n- **Rich metadata**: Display names and descriptions for better UX\n- **Easy maintenance**: No code changes needed for new files\n- **Flexible naming**: Use any filename you want\n- **Future-proof**: Works with any vocabulary format\n\n## Features (v4.50)\n\n- Core flashcard flow: Reveal / Next / Mistake, progress indicator, live mistake count\n- Sessions: full event log; save checkpoints; export/import to JSON; replay only mistaken cards\n- Vocabulary management: 📚 button for importing HSK files and custom vocabulary sets\n- Mobile‑friendly layout; single‑tap mistake toggle on mobile; swipe left/right for next/back\n- Settings (gear):\n  - Auto‑reveal + seconds and countdown\n  - Minimal UI\n  - Outdoor mode (high contrast) and Light/Dark theme\n  - Audio feedback beeps on mark/unmark\n  - Voice section: Browser TTS or OpenAI TTS (model, voice, cache, API key test), Voice speed slider\n  - Info panel (version/build/checkpoint/session)\n- Mic (🎙️) Tone visualizer: live pitch trace, final contour, recorded spectrogram, re‑record/stop/replay controls\n- Speaker (🔊) for pronunciation\n\n## UI and controls\n\n- Top bar: 📚 Vocabulary Manager, New Run, Replay…, Save Progress, Mistake, Gear\n- Above card (right): 🎙️ Tone visualizer, 🔊 Speak\n- Bottom bar: Back, Reveal, Mistake, Next, Save Progress\n- Keyboard:\n  - Space / ↑ / ↓: Reveal / Unreveal\n  - Enter / →: Next\n  - ←: Back\n  - M: Mistake toggle\n  - R: Open Replay dialog\n\n## Export / Import\n\n- Found in the Gear menu and also the Replay dialog; drag‑and‑drop supported.\n- Exports `flash_sessions_YYYYMMDD.json` of all sessions; includes the current in‑progress run snapshot so mid‑run mistakes are preserved.\n- Import merges sessions by `id`; supports multiple JSON shapes.\n- **Format documentation**: See [`data/JSON_FORMAT.md`](data/JSON_FORMAT.md) for complete JSON structure specifications.\n\n## File structure\n\n```text\nindex.html\ncss/\n  style.css\njs/\n  main.js    // boot, wiring, flow\n  data.js    // CSV fetch/parse/normalize, level discovery\n  state.js   // run state, session logging, finalize\n  ui.js      // render, counters, progress/mistake views\n  util.js    // hash, helpers\n  storage.js // LocalStorage, export/import, settings\n  speech.js  // TTS (browser/OpenAI)\n  toneVisualizer.js // mic + pitch visualization\ndata/\n  vocab.csv          # Vocabulary file index\n  hsk*.csv           # HSK vocabulary files\n  *.csv              # Other vocabulary files\n```\n\n## Privacy\n\nAll learning data (sessions, progress, vocabulary) is stored locally in your browser.  \nThe app has no backend server and does not transmit your personal data.  \n\nSome optional features (e.g. speech recognition) use third-party browser APIs such as the Google Web Speech API.  \nIn those cases, audio may be processed by the browser provider’s servers. The app itself never stores or sends speech data externally.\n\n## Troubleshooting\n\n- Browser blocks CSV on `file://`: run `python3 -m http.server` and open the local URL.\n- No vocabulary files showing: ensure `data/vocab.csv` exists and contains valid entries, or check that CSV files exist in `data/` directory; the vocabulary manager will populate automatically on reload.\n- Exported file seems empty: finish a run or mark some mistakes; in‑progress runs are also exported.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foduerr%2Fhsk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foduerr%2Fhsk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foduerr%2Fhsk/lists"}