Files
language4english/LearnEnglish/LearnEnglish/Models/Quiz.swift
T
2026-07-20 21:22:13 +08:00

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()
}
}