Files
mediaplayer/ios/OralTrainer/Models/AssessmentModels.swift
2026-08-17 20:13:28 +08:00

99 lines
4.7 KiB
Swift

import Foundation
struct ImitationAssessmentRequest {
let mediaId: String
let sentence: SentenceBoundary
let recordingURL: URL
let locale: String?
}
struct TextSubstitution: Decodable {
let expected: String
let actual: String
}
struct ImitationAssessmentResult: Decodable {
let attemptId: String?
let scoringVersion: String?
let overallScore: Float
let passed: Bool?
let passScore: Float?
let contentScore: Float?
let completenessScore: Float?
let fluencyScore: Float?
let pronunciationScore: Float?
let prosodyScore: Float?
let durationScore: Float?
let pauseScore: Float?
let speechRateScore: Float?
let referenceText: String?
let recognizedText: String?
let referenceDurationMs: Int64?
let referenceSpeechDurationMs: Int64?
let studentRecordingDurationMs: Int64?
let studentSpeechDurationMs: Int64?
let durationRatio: Float?
let missingTokens: [String]
let extraTokens: [String]
let substitutions: [TextSubstitution]
let feedback: String?
let details: [String: String]
private enum CodingKeys: String, CodingKey {
case attemptId = "attempt_id"
case scoringVersion = "scoring_version"
case overallScore = "overall_score"
case passed
case passScore = "pass_score"
case contentScore = "content_score"
case completenessScore = "completeness_score"
case fluencyScore = "fluency_score"
case pronunciationScore = "pronunciation_score"
case prosodyScore = "prosody_score"
case durationScore = "duration_score"
case pauseScore = "pause_score"
case speechRateScore = "speech_rate_score"
case referenceText = "reference_text"
case recognizedText = "recognized_text"
case referenceDurationMs = "reference_duration_ms"
case referenceSpeechDurationMs = "reference_speech_duration_ms"
case studentRecordingDurationMs = "student_recording_duration_ms"
case studentSpeechDurationMs = "student_speech_duration_ms"
case durationRatio = "duration_ratio"
case missingTokens = "missing_tokens"
case extraTokens = "extra_tokens"
case substitutions
case feedback
case details
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
attemptId = try container.decodeIfPresent(String.self, forKey: .attemptId)
scoringVersion = try container.decodeIfPresent(String.self, forKey: .scoringVersion)
overallScore = try container.decodeIfPresent(Float.self, forKey: .overallScore) ?? 0
passed = try container.decodeIfPresent(Bool.self, forKey: .passed)
passScore = try container.decodeIfPresent(Float.self, forKey: .passScore)
contentScore = try container.decodeIfPresent(Float.self, forKey: .contentScore)
completenessScore = try container.decodeIfPresent(Float.self, forKey: .completenessScore)
fluencyScore = try container.decodeIfPresent(Float.self, forKey: .fluencyScore)
pronunciationScore = try container.decodeIfPresent(Float.self, forKey: .pronunciationScore)
prosodyScore = try container.decodeIfPresent(Float.self, forKey: .prosodyScore)
durationScore = try container.decodeIfPresent(Float.self, forKey: .durationScore)
pauseScore = try container.decodeIfPresent(Float.self, forKey: .pauseScore)
speechRateScore = try container.decodeIfPresent(Float.self, forKey: .speechRateScore)
referenceText = try container.decodeIfPresent(String.self, forKey: .referenceText)
recognizedText = try container.decodeIfPresent(String.self, forKey: .recognizedText)
referenceDurationMs = try container.decodeIfPresent(Int64.self, forKey: .referenceDurationMs)
referenceSpeechDurationMs = try container.decodeIfPresent(Int64.self, forKey: .referenceSpeechDurationMs)
studentRecordingDurationMs = try container.decodeIfPresent(Int64.self, forKey: .studentRecordingDurationMs)
studentSpeechDurationMs = try container.decodeIfPresent(Int64.self, forKey: .studentSpeechDurationMs)
durationRatio = try container.decodeIfPresent(Float.self, forKey: .durationRatio)
missingTokens = try container.decodeIfPresent([String].self, forKey: .missingTokens) ?? []
extraTokens = try container.decodeIfPresent([String].self, forKey: .extraTokens) ?? []
substitutions = try container.decodeIfPresent([TextSubstitution].self, forKey: .substitutions) ?? []
feedback = try container.decodeIfPresent(String.self, forKey: .feedback)
details = try container.decodeIfPresent([String: String].self, forKey: .details) ?? [:]
}
}