Files
ai_english/client/lib/features/speaking/models/pronunciation_assessment.dart
2025-11-17 13:39:05 +08:00

176 lines
5.1 KiB
Dart

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<String> phonemes;
final List<double> 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<String, dynamic> json) {
return WordPronunciation(
word: json['word'] as String,
accuracyScore: (json['accuracyScore'] as num).toDouble(),
errorType: json['errorType'] as String?,
phonemes: List<String>.from(json['phonemes'] ?? []),
phonemeScores: List<double>.from(
(json['phonemeScores'] as List<dynamic>? ?? [])
.map((e) => (e as num).toDouble()),
),
startTime: json['startTime'] as int,
endTime: json['endTime'] as int,
);
}
Map<String, dynamic> 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<PronunciationCriteria, double> scores; // 0-100
final double overallScore; // 0-100
final List<WordPronunciation> wordDetails;
final List<String> suggestions;
final DateTime assessedAt;
final Map<String, dynamic>? 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<String, dynamic> json) {
final scoresMap = <PronunciationCriteria, double>{};
final scoresJson = json['scores'] as Map<String, dynamic>? ?? {};
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<dynamic>? ?? [])
.map((e) => WordPronunciation.fromJson(e as Map<String, dynamic>))
.toList(),
suggestions: List<String>.from(json['suggestions'] ?? []),
assessedAt: DateTime.parse(json['assessedAt'] as String),
metadata: json['metadata'] as Map<String, dynamic>?,
);
}
Map<String, dynamic> toJson() {
final scoresJson = <String, double>{};
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<String> get mainIssues {
final issues = <String>[];
if (scores[PronunciationCriteria.accuracy]! < 70) {
issues.add('发音准确性需要提高');
}
if (scores[PronunciationCriteria.fluency]! < 70) {
issues.add('语音流利度有待改善');
}
if (scores[PronunciationCriteria.prosody]! < 70) {
issues.add('语调和节奏需要调整');
}
return issues;
}
}