TutorLoom
기업·대학·교육기관을 위한 학습 플랫폼, 무료 오픈소스이며 엔터프라이즈 버전 제공
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗App web (PWA) para practicar chino mandarín y español: lecciones graduadas, exámenes (HSK, TOCFL, DELE), práctica diaria con SRS, lectura de clásicos con pinyin/tonos, evaluación de pronunciación por voz y síntesis de audio (TTS) vía Microsoft Edge neural voices.
Estado actual: app.js (el "cerebro" de la app) se modularizó — pasó de
9.451 líneas en un solo archivo a 4.116 líneas, con 11 módulos separados
por función (audio, diccionario, trazos, mazo de repaso, lectores, etc.). Ver
docs/historial-actualizaciones/ para el
detalle de cada versión.
| Archivo | Qué hace |
|---|---|
index.html | Estructura HTML + carga todos los scripts en el orden correcto |
app.js | Núcleo: estado, eventos, lógica de juego (checkAnswer/markWord), dropdowns de módulos, popup de vocabulario, PWA |
style.css | Estilos |
sw.js | Service worker — cachea todo para que la app funcione offline |
app.js (extraídos, cada uno una responsabilidad)| Archivo | Qué contiene |
|---|---|
audio-tts.js | Velocidad, elección de voz, pedido de TTS al servidor con su fallback, playAudio |
dict.js | Motor de búsqueda del diccionario (toque en una palabra → traducción) |
trazos.js | Escritor de trazos Hanzi Writer (orden de trazos, práctica, respuesta a mano) |
srs.js | Mazo de repaso espaciado (Leitner de 6 cajas) |
reader.js | Lector de texto libre (pegás texto y lo lee, con pinyin interlineal) |
karaoke.js | Resaltado de caracteres al ritmo del audio (lector/clásicos) |
classics-reader.js | Lector de los 9 clásicos chinos |
lessons-graduated.js | Quiz de lecciones graduadas HSK 3.0/TOCFL |
placement-test.js | Test de colocación HSK adaptativo |
minimal-pairs.js | Ejercicio de pares mínimos (discriminación tonal) |
data-embedded.js | Datos: oraciones de práctica y vocabulario embebido (ver Cómo agregar contenido nuevo) |
Todos son scripts clásicos (sin import/export) que se cargan en orden
desde index.html — mismas variables/funciones globales que antes, solo que
repartidas en archivos más chicos.
| Archivo | Qué es |
|---|---|
lessons.js, lessons-tocfl.js, lessons-extra.js, lessons-dele.js | Lecciones graduadas y textos largos |
classics.js | Los 9 clásicos chinos (texto original) |
dict-mini.js | Diccionario offline zh↔es |
data-embedded.js | Oraciones de práctica + vocabulario HSK/TOCFL |
data/ | Datos de exámenes en JSON (respaldo, poco usado — casi todo está embebido) |
| Archivo | Qué hace |
|---|---|
voice-evaluator.js, VoiceRecorder.js, pitch-analyzer.js, config.js | Evaluador de pronunciación (Whisper WASM local + análisis de tono) |
api/ | Endpoint serverless (Vercel, Python) para TTS (/api/tts) |
| Archivo | Qué es |
|---|---|
stats.js, onboarding.js, text-utils.js | Estadísticas, onboarding y utilidades de texto |
manifest.json, icons/ | PWA instalable |
README-Pronunciacion.md | Documentación viva del módulo de pronunciación |
docs/historial-actualizaciones/ | Notas de actualización de versiones anteriores (histórico, ya aplicadas) |
README-Pronunciacion.md.LEEME-* de versiones anteriores,
ya integrados en el código actual): ver
docs/historial-actualizaciones/.Ninguno de estos cambios toca app.js ni los demás módulos de lógica —
son archivos de puro contenido.
Archivo: lessons.js (o lessons-tocfl.js/lessons-extra.js/lessons-dele.js
según el examen). Cada entrada de window.LESSONS_DATA.lessons es un objeto:
{
id: 'mi-leccion-1', // único, requerido
title: 'En el mercado', // nombre completo
label: 'Mercado (corto)', // opcional: nombre corto en la Biblioteca
group: 'Vida diaria', // opcional: agrupa en la Biblioteca
module: 'Mercado', // TODO el módulo de oraciones es la lección
// — o en vez de "module" —
// ids: [101, 102, 103], // oraciones puntuales = una SECCIÓN
text_simp: '你好...(texto completo simplificado)',
text_trad: '你好...(texto completo tradicional, opcional)',
hsk: 2 // opcional: nivel HSK de una lectura graduada
}
Si todavía no tenés el texto listo, agregala con status: 'planned': aparece
en la Biblioteca como "· próximamente" (deshabilitada) hasta que la
completes.
___)Archivo: data-embedded.js → EMBEDDED_SENTENCES (módulo base "todas") o
EMBEDDED_MODULE_DATA['NombreDelMódulo'] (un módulo específico). Cada
entrada:
{
"id": 999,
"level": 1,
"module": "Saludos",
"spanish_full": "Hola, ¿cómo estás?",
"spanish_cloze": "___, ¿cómo estás?",
"spanish_answer": "Hola",
"chinese_simp_full": "你好,你好吗?",
"chinese_simp_cloze": "___,你好吗?",
"chinese_simp_answer": "你好",
"chinese_trad_full": "你好,你好嗎?",
"chinese_trad_cloze": "___,你好嗎?",
"chinese_trad_answer": "你好",
"pinyin": "Nǐ hǎo, nǐ hǎo ma?"
}
___ marca el hueco que hay que completar; *_full es la oración
completa y *_answer la respuesta esperada.
Archivo: data-embedded.js → EMBEDDED_MODULE_DATA['HSK3'] (o el nivel que
sea). Viaja como tupla compacta, no como objeto, para que el archivo pese
menos — se expande sola con expandWordCards() al abrir el módulo:
["爱", "愛", "ài", "Amar", ["Gustar"]]
// [simplificado, tradicional|null, pinyin, español, alternativas|null]
Si el tradicional es igual al simplificado, poné null en su lugar (ej.
["八", null, "bā", "Ocho", null]).
Archivo: classics.js. Cada entrada de window.CLASSIC_TEXTS[claveDelMódulo]:
"Clasicos-MiClasico": {
es: "Nombre en español", emoji: "📜", badge: "completo",
intro: "Una línea de descripción.",
blocks: [
{ n: "Capítulo 1", l: [
["原文en chino.", "Traducción al español."],
["Otra línea del bloque.", "Su traducción."]
] }
]
}
El tradicional se genera aparte (mapas T_LINE/T_TITLE horneados con
opencc) — no hace falta escribirlo a mano si solo estás agregando texto
nuevo con la traducción en es.
VERSION en sw.js (línea const VERSION = 'vNNN')
para que el service worker le avise a todos los dispositivos que hay
contenido nuevo — si no, quien ya tiene la app instalada puede seguir
viendo la versión vieja cacheada un tiempo.id de oración, no lo repitas con uno ya existente en el
mismo archivo.index.html.vercel.json + api/), Microsoft Edge neural
voices vía edge-tts.sw.js) versiona la caché de shell y de audios; al
subir cambios de cualquier .js/index.html/style.css/sw.js conviene
refresco forzado (Ctrl+Shift+R) para evitar ver la versión cacheada.pip install -r requirements.txt
python serve.py