{"id":51061349,"url":"https://github.com/sedoglia/hsk1-simulator","last_synced_at":"2026-06-23T02:30:24.469Z","repository":{"id":363895955,"uuid":"1265452834","full_name":"sedoglia/hsk1-simulator","owner":"sedoglia","description":"HSK1 Chinese exam simulator — 40-question practice test with TTS, real photos, bilingual UI (IT/EN)","archived":false,"fork":false,"pushed_at":"2026-06-10T20:05:12.000Z","size":3037,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-10T21:15:09.089Z","etag":null,"topics":["chinese","exam-simulator","hsk","hsk1","language-learning","mandarin","python","study-tool","text-to-speech","tkinter"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sedoglia.png","metadata":{"files":{"readme":"README.it.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-10T19:39:28.000Z","updated_at":"2026-06-10T20:06:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/sedoglia/hsk1-simulator","commit_stats":null,"previous_names":["sedoglia/hsk1-simulator"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sedoglia/hsk1-simulator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sedoglia%2Fhsk1-simulator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sedoglia%2Fhsk1-simulator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sedoglia%2Fhsk1-simulator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sedoglia%2Fhsk1-simulator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sedoglia","download_url":"https://codeload.github.com/sedoglia/hsk1-simulator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sedoglia%2Fhsk1-simulator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34673437,"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-23T02:00:07.161Z","response_time":65,"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":["chinese","exam-simulator","hsk","hsk1","language-learning","mandarin","python","study-tool","text-to-speech","tkinter"],"created_at":"2026-06-23T02:30:22.628Z","updated_at":"2026-06-23T02:30:24.459Z","avatar_url":"https://github.com/sedoglia.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Simulatore d'esame HSK1\n\n\u003e **English version → [README.md](README.md)**\n\nUn'applicazione desktop **Python / Tkinter** che replica fedelmente l'esame ufficiale di\ncertificazione cinese **HSK di livello 1**, basata sul 考试大纲 (syllabus ufficiale) e sul\n样卷 (prova campione) del Centro per l'Educazione e la Cooperazione Linguistica\n(CLEC / 教育部中外语言交流合作中心), verificata contro gli esami reali H10901–H11005.\n\nOgni esecuzione genera un test da 40 domande **completamente diverso**. L'app gira interamente\nsu Windows, funziona offline (con TTS degradato) e non richiede account né abbonamenti.\n\n---\n\n## Indice\n\n1. [Struttura dell'esame](#struttura-dellesame)\n2. [Funzionalità](#funzionalità)\n3. [Requisiti](#requisiti)\n4. [Installazione](#installazione)\n5. [Avvio dell'applicazione](#avvio-dellapplicazione)\n6. [Esecuzione dei test automatici](#esecuzione-dei-test-automatici)\n7. [Struttura del progetto](#struttura-del-progetto)\n8. [File di dati](#file-di-dati)\n9. [Estendere l'applicazione](#estendere-lapplicazione)\n10. [Note tecniche](#note-tecniche)\n11. [Licenza](#licenza)\n\n---\n\n## Struttura dell'esame\n\nL'esame HSK1 ha due sezioni e 40 domande totali, ciascuna del valore di 5 punti.\n\n| | Ascolto 听力 (~15 min) | Lettura 阅读 (17 min) |\n|---|---|---|\n| **Parte 1** | Frase breve → immagine **Vero / Falso** | Parola + immagine **Vero / Falso** |\n| **Parte 2** | Frase → scegli **1 tra 3** immagini (A/B/C) | Frase → scegli **1 tra 6** immagini (A–F) |\n| **Parte 3** | Dialogo → scegli **1 tra 6** immagini (A–F) | Domanda → abbina **1 di 6** risposte (A–F) |\n| **Parte 4** | Enunciato + domanda → scegli **1 di 3** risposte | Completa il buco (banco di **6** parole) |\n\n**Tempi**: ~15 min Ascolto · +3 min per la scheda risposte · 17 min Lettura ·\n~40 min totali (inclusi 5 min per i dati personali).\n\n**Punteggio**: Ascolto / 100 + Lettura / 100 = **/ 200** · **Sufficienza ≥ 120 / 200**.\n\nOgni quesito di Ascolto viene **riprodotto due volte**, come nell'esame reale.\nTutte le domande mostrano il **pinyin**, come stabilito dal syllabus ufficiale\n(*\"试卷上的试题都有拼音\"*). Ogni parte si apre con un **esempio svolto** (例如),\nidentico al foglio ufficiale.\n\n---\n\n## Funzionalità\n\n### Riproduzione fedele dell'esame\n- Una parte intera (5 quesiti) per schermata, navigabile con Avanti / Indietro.\n- Le parti ad abbinamento (A3, L2, L3, L4) mostrano un **banco A–F condiviso** in cima alla\n  schermata; il candidato sceglie la lettera corrispondente per ciascun quesito — esattamente\n  come nel foglio ufficiale a stampa.\n- La selezione della risposta avviene sul posto (senza ricaricare la pagina), quindi la\n  posizione di scroll non salta mai.\n\n### Generazione randomica delle domande\nLe domande vengono generate nuove a ogni esecuzione a partire da banche curate:\n\n| Banca | Elementi | Usata in |\n|---|---|---|\n| `sentences.json` | 123 frasi naturali HSK1 | A2, L2 |\n| `dialogues.json` | 64 coppie dialogo Q\u0026R | A3, L3 |\n| `grammar.json` | 64 esercizi di completamento | L4 |\n| `vocab_hsk1.json` | 295 parole HSK1 | A1, L1, A4, distrattori |\n\nTutti i contenuti usano **solo vocabolario ufficiale HSK1** (syllabus da 150 parole).\nLa difficoltà delle frasi, dei dialoghi e dei completamenti è stata confrontata\nstatisticamente con gli esami reali e risulta allo stesso livello.\n\n### Sintesi vocale\n- **Online (alta qualità)**: `edge-tts` con la voce Microsoft Xiaoxiao Neural (`zh-CN-XiaoxiaoNeural`).\n- **Fallback offline**: `pyttsx3` con voce cinese Windows SAPI (se installata).\n- **Velocità adattiva**: la velocità di lettura rallenta per le frasi più lunghe, in modo che\n  ogni parola sia più facile da seguire (−10 % per ≤ 4 caratteri, fino a −38 % per \u003e 10 caratteri).\n- Tutto l'audio viene **conservato su disco** per hash del contenuto, così viene sintetizzato\n  una sola volta.\n- All'avvio dell'esame viene riprodotta una clip silenziosa di riscaldamento per evitare che\n  la prima sillaba venga tagliata dal driver audio di Windows.\n\n### Immagini\n- **32 scene curate** (`assets/scenes/`) abbinate manualmente a frasi specifiche.\n- **70+ foto con licenza CC** (`assets/words/`) provenienti da [Openverse](https://openverse.org),\n  che coprono tutti i 53 concetti illustrabili dell'HSK1.\n- Ogni concetto ha **almeno 2 foto diverse**, quindi test ripetuti mostrano immagini diverse.\n- In una domanda, tutte le opzioni sono sempre foto (mai un mix di foto ed emoji), così il\n  tipo di immagine non può rivelare la risposta.\n- I crediti delle foto CC sono salvati in `data/image_credits.json`.\n\n### Punteggio e storico\n- Il calcolo del punteggio segue il modello lineare ufficiale: ogni risposta corretta = 5 punti per sezione.\n- Ogni tentativo viene salvato in un **database SQLite** locale con:\n  - Data e ora\n  - Punteggi Ascolto / Lettura / Totale\n  - Dettaglio per-parte (corrette / totali per ciascuna delle 8 parti)\n  - Durata in secondi\n  - Lingua dell'interfaccia usata\n- La **schermata Storico** mostra una tabella scorrevole (con colonna Durata) e un grafico\n  a linee del punteggio totale nel tempo, con linea tratteggiata di sufficienza a 120.\n- I risultati possono essere **eliminati** singolarmente dalla schermata Risultati e dalla\n  schermata Storico; un pulsante **Azzera tutto** cancella l'intero storico (con conferma).\n\n### Interfaccia utente\n- **Bilingue** Italiano / Inglese: commutabile al volo con il pulsante IT / EN nell'header.\n- **Timer a conto alla rovescia per sezione**: modalità rigida che avanza automaticamente allo\n  scadere del tempo; modalità rilassata senza limite.\n- **Revisione delle risposte**: dopo l'esame, un elenco scorrevole mostra ogni domanda con\n  la risposta corretta, la tua risposta, il pinyin, la traduzione italiano/inglese e un pulsante\n  Riascolta per le domande di Ascolto.\n- **Schermata Impostazioni**: timer rigido sì/no · mostra/nascondi pinyin · prova della voce ·\n  mostra/nascondi esempi svolti (例如).\n\n---\n\n## Requisiti\n\n| Dipendenza | Scopo |\n|---|---|\n| Python 3.10+ (testato su 3.14) | runtime |\n| `edge-tts` | TTS neurale online |\n| `pyttsx3` | TTS offline di fallback |\n| `pypinyin` | generazione del pinyin |\n| `Pillow` | caricamento foto, rasterizzazione emoji |\n| `tkinter` | GUI (incluso in Python su Windows) |\n| `sqlite3` | storico (incluso in Python) |\n\nNessuna dipendenza pesante come `pygame`. La riproduzione audio usa l'**API MCI di Windows**\ntramite `ctypes`, che supporta nativamente MP3 e WAV.\n\n---\n\n## Installazione\n\n```powershell\n# 1. Clona il repository\ngit clone https://github.com/sedoglia/hsk1-simulator.git\ncd hsk1-simulator\n\n# 2. Installa le dipendenze\npip install -r requirements.txt\n\n# 3. Avvia\npython run.py\n```\n\n---\n\n## Avvio dell'applicazione\n\n```powershell\npython run.py\n```\n\nL'app si apre sulla **schermata Home**. Premi **Inizia il test** per cominciare. La sezione\nAscolto carica e pre-sintetizza l'audio (con barra di avanzamento); la sezione Lettura parte\nimmediatamente.\n\nAlla fine premi **Termina e correggi** per vedere il punteggio. Dalla schermata Risultati puoi:\n- Espandere **Rivedi le risposte** per leggere ogni Q\u0026R con riascolto audio.\n- Premere **Inizia il test** per un nuovo esame randomico.\n- Andare a **Storico e progressi** per vedere tutti i risultati passati.\n\n---\n\n## Esecuzione dei test automatici\n\n```powershell\npython -m unittest discover -s tests -v\n```\n\n31 test in tre file:\n\n| File | Test | Cosa viene verificato |\n|---|---|---|\n| `test_exam_structure.py` | 19 | 40 domande, 4×5 per sezione, tipi per parte, tempi, punteggio, condivisione banco A–F, conformità alle 150 ufficiali, casualità |\n| `test_images.py` | 9 | ≥ 50 concetti illustrati, tutti i file esistono su disco, nessun mix foto/emoji in una domanda, immagini distinte per domanda, varietà su 40 esami |\n| `test_audio.py` | 3 | riproduzione sequenziale, stop annulla le clip rimanenti, la seconda clip non parte prima che finisca la prima |\n\n---\n\n## Struttura del progetto\n\n```\nhsk1-simulator/\n│\n├── run.py                      # punto di avvio — python run.py\n├── requirements.txt\n├── README.md                   # versione inglese\n├── README.it.md                # questo file (italiano)\n│\n├── hsk1sim/                    # pacchetto principale\n│   ├── config.py               # tutti i percorsi, costanti d'esame, flag di configurazione\n│   ├── i18n.py                 # tutte le stringhe UI in IT e EN; classe Translator\n│   ├── tts.py                  # HybridTTS: edge-tts + pyttsx3, cache su disco, velocità adattiva\n│   ├── audio.py                # AudioPlayer via Windows MCI (play, play_sequence, stop, warmup)\n│   ├── emoji_render.py         # visual_to_image(): foto o emoji → Tkinter PhotoImage\n│   ├── visual_catalog.py       # mappa frasi/parole → percorsi immagini; carica word_images.json\n│   ├── exam.py                 # modello Exam: generate(), score(), details(), duration_seconds()\n│   ├── question_gen.py         # 8 generatori (uno per parte) + template frasi/dialoghi\n│   ├── db.py                   # SQLite: save_attempt(), get_attempts(), delete_attempt(), clear()\n│   │\n│   ├── assets/\n│   │   ├── scenes/             # s01.jpg … s32.jpg — scene curate per l'esame\n│   │   └── words/              # foto CC per concetti (apple_1.jpg, doctor_1.jpg, …)\n│   │\n│   ├── data/\n│   │   ├── vocab_hsk1.json     # 295 parole: hanzi, pinyin, it, en, emoji, category, hsk1_official\n│   │   ├── official_150.json   # lista dei 150 hanzi del syllabus ufficiale HSK1\n│   │   ├── sentences.json      # 123 frasi: zh, it, en, key (concetto-immagine)\n│   │   ├── dialogues.json      # 64 dialoghi: q, a, q_it/en, a_it/en, key\n│   │   ├── grammar.json        # 64 item completamento: q, a, d (distrattori), pt_it, pt_en, it, en\n│   │   ├── word_images.json    # { hanzi: [\"words/file.jpg\", …] } — indice foto CC\n│   │   └── image_credits.json  # { \"words/file.jpg\": { creator, license, source } }\n│   │\n│   └── ui/\n│       ├── app.py              # classe App: finestra root, router schermate, toggle lingua\n│       ├── welcome.py          # schermata Home\n│       ├── exam_view.py        # schermata Esame: per-parte, banco A–F, controlli audio\n│       ├── results.py          # schermata Risultati: punteggi, revisione risposte, pulsante elimina\n│       ├── history.py          # schermata Storico: tabella + grafico + pulsanti elimina/azzera\n│       ├── settings_view.py    # schermata Impostazioni\n│       └── widgets.py          # tema colori condiviso, helper f() per font, helper button()\n│\n├── tests/\n│   ├── test_exam_structure.py\n│   ├── test_images.py\n│   └── test_audio.py\n│\n└── userdata/                   # creata al primo avvio (esclusa da git)\n    ├── history.db              # storico dei tentativi in SQLite\n    └── audio_cache/            # file MP3/WAV sintetizzati, indicizzati per hash del contenuto\n```\n\n---\n\n## File di dati\n\n### `vocab_hsk1.json`\nArray di oggetti-parola. Ogni elemento:\n```json\n{\n  \"hanzi\": \"学校\",\n  \"pinyin\": \"xuéxiào\",\n  \"it\": \"scuola\",\n  \"en\": \"school\",\n  \"emoji\": \"🏫\",\n  \"category\": \"place\",\n  \"hsk1_official\": true\n}\n```\n`hsk1_official: true` indica che la parola è nel syllabus ufficiale da 150 parole.\nImposta `OFFICIAL_150_ONLY = False` in `config.py` per usare il set esteso da ~295 voci.\n\n### `sentences.json`\nFrasi naturali HSK1 collegate a un concetto illustrabile (`key`):\n```json\n{ \"zh\": \"他在学校工作。\", \"it\": \"Lavora a scuola.\", \"en\": \"He works at school.\", \"key\": \"学校\" }\n```\n\n### `dialogues.json`\nCoppie Q\u0026R, alcune collegate a un concetto (`key`) per l'uso nell'Ascolto Parte 3:\n```json\n{ \"q\": \"你去哪儿？\", \"a\": \"我去学校。\", \"q_it\": \"Dove vai?\", \"q_en\": \"Where are you going?\",\n  \"a_it\": \"Vado a scuola.\", \"a_en\": \"I'm going to school.\", \"key\": \"学校\" }\n```\n\n### `grammar.json`\nItem di completamento. `a` è la parola corretta; `d` è una lista di due distrattori plausibili:\n```json\n{ \"q\": \"他 （ ____ ） 学校。\", \"a\": \"在\", \"d\": [\"是\", \"有\"],\n  \"pt_it\": \"在 per il luogo\", \"pt_en\": \"在 for location\",\n  \"it\": \"Lui è a scuola.\", \"en\": \"He is at school.\" }\n```\n\n---\n\n## Estendere l'applicazione\n\n### Rigenerare il vocabolario\n```powershell\npython build_vocab.py\n```\nLegge la lista di parole in `build_vocab.py`, calcola il pinyin con `pypinyin` e scrive\n`hsk1sim/data/vocab_hsk1.json`. Modifica la lista `WORDS` per aggiungere o cambiare voci.\n\n### Scaricare altre foto CC\n```powershell\npython fetch_images.py   # scarica 2 foto per concetto (prima esecuzione)\npython fetch_more.py     # integra i concetti che hanno meno di 2 foto\n```\nEntrambi gli script interrogano le API di [Openverse](https://openverse.org) (nessuna chiave\nrichiesta) e salvano le foto in `hsk1sim/assets/words/`. I crediti vengono scritti in\n`data/image_credits.json`.\n\n### Verificare la conformità all'HSK1\n```powershell\npython validate_banks.py\n```\nTokenizza ogni frase e dialogo con un segmentatore max-match e segnala qualsiasi parola\ncinese che non è nelle 150 ufficiali (o nei morfemi esplicitamente ammessi).\n\n---\n\n## Note tecniche\n\n- **Anti-troncamento audio**: una WAV silenziosa da 350 ms viene riprodotta una volta\n  all'avvio dell'esame (`player.warmup()`) per inizializzare il dispositivo audio di Windows,\n  evitando che la prima sillaba venga tagliata. Ogni clip usa anche MCI `cue output` +\n  `seek to start` prima della riproduzione.\n- **Thread safety**: la barra di caricamento viene aggiornata tramite una `queue.Queue`\n  interrogata sul thread principale (ogni 80 ms), non tramite chiamate `after()` dal thread\n  worker.\n- **Persistenza dello scroll**: fare clic su una risposta chiama una closure leggera\n  `_refresh()` che ricolora solo i widget coinvolti sul posto, quindi la posizione di scroll\n  non salta mai.\n- **Deduplicazione delle immagini**: il generatore `_distinct_image_items()` garantisce che\n  tutte le opzioni in una domanda ad abbinamento puntino a file di immagini diversi, anche\n  quando due concetti condividono la stessa scena curata.\n- **Bilanciamento del banco R4**: la Lettura Parte 4 seleziona ~3 item \"ricchi\" (parole di\n  contenuto o frasi composte) e ~2 item \"base\" (parole grammaticali / frasi brevi) per esame,\n  corrispondendo alla composizione del banco parole degli esami ufficiali.\n\n---\n\n## Licenza\n\n**Codice**: MIT — vedi [LICENSE](LICENSE).\n\n**Foto in `assets/words/`**: CC0 o CC-BY, vedi `data/image_credits.json` per le attribuzioni.\n\n**Foto in `assets/scenes/`**: curate per questo progetto; libere per uso didattico personale.\n\n**Esami ufficiali Hanban** (H10901–H11005, non inclusi in questo repository):\n© Hanban / Center for Language Education and Cooperation. Scaricabili separatamente da\n[chinesetest.cn](https://www.chinesetest.cn) o da distributori autorizzati.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsedoglia%2Fhsk1-simulator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsedoglia%2Fhsk1-simulator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsedoglia%2Fhsk1-simulator/lists"}