3d2466edba
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
61 lines
2.1 KiB
Swift
61 lines
2.1 KiB
Swift
import Foundation
|
|
|
|
enum WordStoreError: Error, LocalizedError {
|
|
case fileNotFound
|
|
case decodingFailed(Error)
|
|
|
|
var errorDescription: String? {
|
|
switch self {
|
|
case .fileNotFound: return "词库文件缺失"
|
|
case .decodingFailed(let error): return "词库解析失败:\(error.localizedDescription)"
|
|
}
|
|
}
|
|
}
|
|
|
|
final class WordStore {
|
|
private(set) var bank: WordBank?
|
|
private(set) var loadError: String?
|
|
|
|
var categories: [WordCategory] { bank?.categories ?? [] }
|
|
|
|
func load() {
|
|
guard bank == nil, loadError == nil else { return }
|
|
guard let url = Bundle.main.url(forResource: "words", withExtension: "json") else {
|
|
loadError = WordStoreError.fileNotFound.localizedDescription
|
|
return
|
|
}
|
|
do {
|
|
let data = try Data(contentsOf: url)
|
|
let decoded = try JSONDecoder().decode(WordBank.self, from: data)
|
|
let categories = decoded.categories.map { category -> WordCategory in
|
|
var cat = category
|
|
let source: [Word]
|
|
if let subs = cat.subcategories, !subs.isEmpty {
|
|
source = subs.flatMap { $0.words }
|
|
} else {
|
|
source = cat.words
|
|
}
|
|
let tagged: [Word]
|
|
if category.id == "numbers" {
|
|
var words = NumberWords.makeWords(atoms: source)
|
|
let extras = source.filter { NumberWords.atomNumbers[$0.word] == nil }
|
|
words.append(contentsOf: extras)
|
|
tagged = words
|
|
} else {
|
|
tagged = source
|
|
}
|
|
let words = tagged.map { word -> Word in
|
|
var w = word
|
|
w.categoryId = category.id
|
|
return w
|
|
}
|
|
cat.words = words
|
|
return cat
|
|
}
|
|
bank = WordBank(version: decoded.version, categories: categories)
|
|
} catch {
|
|
loadError = WordStoreError.decodingFailed(error).localizedDescription
|
|
}
|
|
}
|
|
}
|