69a1c44ded
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
79 lines
2.5 KiB
Swift
79 lines
2.5 KiB
Swift
import Foundation
|
|
|
|
enum QuizMode: String, Hashable {
|
|
case enToZh = "英选汉"
|
|
case zhToEn = "汉选英"
|
|
case spelling = "拼写"
|
|
case dictation = "默写"
|
|
}
|
|
|
|
struct QuizSetupRequest: Hashable {
|
|
let words: [Word]
|
|
}
|
|
|
|
struct QuizConfig: Hashable {
|
|
let mode: QuizMode
|
|
let words: [Word]
|
|
let isStudyMode: Bool
|
|
|
|
init(mode: QuizMode, words: [Word], isStudyMode: Bool = false) {
|
|
self.mode = mode
|
|
self.words = words
|
|
self.isStudyMode = isStudyMode
|
|
}
|
|
}
|
|
|
|
struct QuizQuestion: Identifiable {
|
|
var id: String { word.id }
|
|
let word: Word
|
|
let prompt: String
|
|
let options: [String]
|
|
let answer: String
|
|
let blankedWord: String
|
|
let blankPositions: [Int]
|
|
}
|
|
|
|
enum QuizGenerator {
|
|
static func makeQuestions(mode: QuizMode, words: [Word]) -> [QuizQuestion] {
|
|
words.shuffled().map { word in
|
|
let distractors = words.filter { $0 != word }.shuffled().prefix(3)
|
|
let options = (distractors.map { optionText($0, mode) } + [optionText(word, mode)]).shuffled()
|
|
let blankedWord = mode == .spelling ? blankWord(word.word) : ""
|
|
let blankPositions = blankedWord.enumerated().filter { $0.element == "_" }.map { $0.offset }
|
|
return QuizQuestion(
|
|
word: word,
|
|
prompt: promptText(word, mode),
|
|
options: options,
|
|
answer: optionText(word, mode),
|
|
blankedWord: blankedWord,
|
|
blankPositions: blankPositions
|
|
)
|
|
}
|
|
}
|
|
|
|
private static func promptText(_ word: Word, _ mode: QuizMode) -> String {
|
|
switch mode {
|
|
case .enToZh: return word.word
|
|
case .zhToEn: return word.meaning
|
|
case .spelling, .dictation: return word.meaning
|
|
}
|
|
}
|
|
|
|
private static func optionText(_ word: Word, _ mode: QuizMode) -> String {
|
|
switch mode {
|
|
case .enToZh: return word.meaning
|
|
case .zhToEn: return word.word
|
|
case .spelling, .dictation: return word.word
|
|
}
|
|
}
|
|
|
|
private static func blankWord(_ word: String) -> String {
|
|
let chars = Array(word)
|
|
let letterPositions = chars.indices.filter { chars[$0].isLetter }
|
|
guard !letterPositions.isEmpty else { return word }
|
|
let blankCount = Int.random(in: 1...letterPositions.count)
|
|
let indices = Set(letterPositions.shuffled().prefix(blankCount))
|
|
return chars.enumerated().map { indices.contains($0.offset) ? "_" : String($0.element) }.joined()
|
|
}
|
|
}
|