enum PronunciationCriteria { accuracy, fluency, completeness, prosody; String get displayName { switch (this) { case PronunciationCriteria.accuracy: return '准确性'; case PronunciationCriteria.fluency: return '流利度'; case PronunciationCriteria.completeness: return '完整性'; case PronunciationCriteria.prosody: return '韵律'; } } String get description { switch (this) { case PronunciationCriteria.accuracy: return '发音的准确程度'; case PronunciationCriteria.fluency: return '语音的流畅程度'; case PronunciationCriteria.completeness: return '内容的完整程度'; case PronunciationCriteria.prosody: return '语调和节奏的自然程度'; } } } class WordPronunciation { final String word; final double accuracyScore; // 0-100 final String? errorType; final List phonemes; final List phonemeScores; final int startTime; // 毫秒 final int endTime; // 毫秒 const WordPronunciation({ required this.word, required this.accuracyScore, this.errorType, required this.phonemes, required this.phonemeScores, required this.startTime, required this.endTime, }); factory WordPronunciation.fromJson(Map json) { return WordPronunciation( word: json['word'] as String, accuracyScore: (json['accuracyScore'] as num).toDouble(), errorType: json['errorType'] as String?, phonemes: List.from(json['phonemes'] ?? []), phonemeScores: List.from( (json['phonemeScores'] as List? ?? []) .map((e) => (e as num).toDouble()), ), startTime: json['startTime'] as int, endTime: json['endTime'] as int, ); } Map toJson() { return { 'word': word, 'accuracyScore': accuracyScore, 'errorType': errorType, 'phonemes': phonemes, 'phonemeScores': phonemeScores, 'startTime': startTime, 'endTime': endTime, }; } } class PronunciationAssessment { final String id; final String conversationId; final String messageId; final String originalText; final String recognizedText; final Map scores; // 0-100 final double overallScore; // 0-100 final List wordDetails; final List suggestions; final DateTime assessedAt; final Map? metadata; const PronunciationAssessment({ required this.id, required this.conversationId, required this.messageId, required this.originalText, required this.recognizedText, required this.scores, required this.overallScore, required this.wordDetails, required this.suggestions, required this.assessedAt, this.metadata, }); factory PronunciationAssessment.fromJson(Map json) { final scoresMap = {}; final scoresJson = json['scores'] as Map? ?? {}; for (final criteria in PronunciationCriteria.values) { scoresMap[criteria] = (scoresJson[criteria.name] as num?)?.toDouble() ?? 0.0; } return PronunciationAssessment( id: json['id'] as String, conversationId: json['conversationId'] as String, messageId: json['messageId'] as String, originalText: json['originalText'] as String, recognizedText: json['recognizedText'] as String, scores: scoresMap, overallScore: (json['overallScore'] as num).toDouble(), wordDetails: (json['wordDetails'] as List? ?? []) .map((e) => WordPronunciation.fromJson(e as Map)) .toList(), suggestions: List.from(json['suggestions'] ?? []), assessedAt: DateTime.parse(json['assessedAt'] as String), metadata: json['metadata'] as Map?, ); } Map toJson() { final scoresJson = {}; for (final entry in scores.entries) { scoresJson[entry.key.name] = entry.value; } return { 'id': id, 'conversationId': conversationId, 'messageId': messageId, 'originalText': originalText, 'recognizedText': recognizedText, 'scores': scoresJson, 'overallScore': overallScore, 'wordDetails': wordDetails.map((e) => e.toJson()).toList(), 'suggestions': suggestions, 'assessedAt': assessedAt.toIso8601String(), 'metadata': metadata, }; } String get accuracyLevel { if (overallScore >= 90) return '优秀'; if (overallScore >= 80) return '良好'; if (overallScore >= 70) return '中等'; if (overallScore >= 60) return '及格'; return '需要改进'; } List get mainIssues { final issues = []; if (scores[PronunciationCriteria.accuracy]! < 70) { issues.add('发音准确性需要提高'); } if (scores[PronunciationCriteria.fluency]! < 70) { issues.add('语音流利度有待改善'); } if (scores[PronunciationCriteria.prosody]! < 70) { issues.add('语调和节奏需要调整'); } return issues; } }