part of '../main.dart'; class SavedAnalysis { const SavedAnalysis({ required this.studentName, required this.studentGender, required this.label, required this.description, required this.confidence, required this.probabilityPd, required this.probabilityTpd, }); factory SavedAnalysis.fromJson(Map json) { return SavedAnalysis( studentName: json['student_name']?.toString() ?? '-', studentGender: json['student_gender']?.toString() ?? '', label: json['predicted_label']?.toString() ?? '-', description: json['description']?.toString() ?? '-', confidence: PredictionResult._asDouble(json['confidence']), probabilityPd: PredictionResult._asDouble(json['probability_pd']), probabilityTpd: PredictionResult._asDouble(json['probability_tpd']), ); } final String studentName; final String studentGender; final String label; final String description; final double confidence; final double probabilityPd; final double probabilityTpd; String get confidencePercent => (confidence * 100).toStringAsFixed(1); String get pdPercent => (probabilityPd * 100).toStringAsFixed(1); String get tpdPercent => (probabilityTpd * 100).toStringAsFixed(1); String get genderLabel => studentGender.isEmpty ? 'Belum diisi' : studentGender; } class PredictionResult { const PredictionResult({ required this.id, required this.studentName, required this.studentGender, required this.isValidAudio, required this.errorMessage, required this.label, required this.description, required this.confidence, required this.probabilityPd, required this.probabilityTpd, required this.audioQuality, required this.explanation, required this.rawJson, }); factory PredictionResult.fromJson(Map json) { final probabilities = (json['probabilities'] as Map?)?.cast() ?? {}; final predictedLabel = json['predicted_label']?.toString(); return PredictionResult( id: json['prediction_id'] is int ? json['prediction_id'] as int : int.tryParse(json['prediction_id']?.toString() ?? ''), studentName: json['student_name']?.toString() ?? '', studentGender: json['student_gender']?.toString() ?? '', isValidAudio: json['is_valid_audio'] != false, errorMessage: json['error_message']?.toString(), label: predictedLabel ?? json['label']?.toString() ?? '-', description: json['description']?.toString() ?? '-', confidence: _asDouble(json['confidence']), probabilityPd: _asDouble(json['probability_pd'] ?? probabilities['PD']), probabilityTpd: _asDouble( json['probability_tpd'] ?? probabilities['TPD'], ), audioQuality: AudioQuality.fromJson( (json['audio_quality'] as Map?)?.cast() ?? {}, ), explanation: json['explanation']?.toString() ?? '', rawJson: json, ); } Map toSaveJson(int userId, String studentGender) { return { ...rawJson, 'student_name': studentName, 'student_gender': studentGender, 'user_id': userId, }; } static double _asDouble(Object? value) { if (value is num) { return value.toDouble(); } return double.tryParse(value?.toString() ?? '') ?? 0.0; } final int? id; final String studentName; final String studentGender; final bool isValidAudio; final String? errorMessage; final String label; final String description; final double confidence; final double probabilityPd; final double probabilityTpd; final AudioQuality audioQuality; final String explanation; final Map rawJson; String get genderLabel => studentGender.isEmpty ? 'Belum diisi' : studentGender; } class AudioQuality { const AudioQuality({ required this.isClipped, required this.isTooQuiet, required this.isTooShort, }); factory AudioQuality.fromJson(Map json) { return AudioQuality( isClipped: json['is_clipped'] == true, isTooQuiet: json['is_too_quiet'] == true, isTooShort: json['is_too_short'] == true, ); } final bool isClipped; final bool isTooQuiet; final bool isTooShort; }