this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 55 lines 2.0 kB view raw
1/** 2 * Curriculum ordering utilities: reading the order files that define which 3 * characters, vocabulary, and radicals are taught, and in what sequence. 4 * 5 * Order files live under data/lang/{targetLang}/order/. 6 */ 7 8import { parse } from '@std/csv/parse' 9import { DATA_ROOT } from './fs.ts' 10import { readDictByHant, type Definition } from './dict.ts' 11 12/** 13 * Reads a vocabulary or radical order CSV (e.g. lang/zh_CN/order/vocabulary.csv). 14 * Returns an array of levels, each level being an array of slugs (traditional forms). 15 */ 16export function readLessonOrder(input: string): string[][] { 17 return parse(Deno.readTextFileSync(DATA_ROOT + input)) as string[][] 18} 19 20/** 21 * Reads a character order file (e.g. lang/zh_CN/order/characters.txt). 22 * Each line is one level; each character in the line is one slug. 23 */ 24export function readCharacterOrder(targetLang: string): string[][] { 25 const text = Deno.readTextFileSync(DATA_ROOT + `lang/${targetLang}/order/characters.txt`) 26 return text.split('\n').map((row) => row.split('')) 27} 28 29/** 30 * Returns the ordered set of definitions for items in the curriculum, deduplicated 31 * and in curriculum order. Only includes items that are actually taught — not the 32 * full dictionary. 33 * 34 * @param type - 'character' or 'vocabulary' 35 * @param targetLang - target language code (default: 'zh_CN') 36 */ 37export function readOrderedDefs( 38 type: 'character' | 'vocabulary', 39 targetLang = 'zh_CN', 40): Definition[] { 41 const [dictPath, slugsList] = type === 'character' 42 ? ['lang/characters.tsv', readCharacterOrder(targetLang).flat()] 43 : ['lang/vocabulary.tsv', readLessonOrder(`lang/${targetLang}/order/vocabulary.csv`).flat()] 44 45 const byHant = readDictByHant(dictPath) 46 const seen = new Set<string>() 47 const result: Definition[] = [] 48 for (const slug of slugsList) { 49 if (!slug || seen.has(slug)) continue 50 seen.add(slug) 51 const def = byHant[slug] 52 if (def) result.push(def) 53 } 54 return result 55}