Files
saqel/apps/student_app/lib/data/models/socratic_checkpoint_model.dart
T

161 lines
5.1 KiB
Dart

/// Model representing an In-Video Socratic Gatekeeping Checkpoint (فحص الفهم السقراطي)
class SocraticCheckpointModel {
final int id;
final String questionText;
final int timestampSeconds;
final int rewindSecondsOnFail;
final String hint;
final String pedagogicalExplanation;
final List<SocraticOptionModel> options;
const SocraticCheckpointModel({
required this.id,
required this.questionText,
required this.timestampSeconds,
this.rewindSecondsOnFail = 45,
this.hint = '',
this.pedagogicalExplanation = '',
this.options = const [],
});
factory SocraticCheckpointModel.fromJson(Map<String, dynamic> json) {
final List<SocraticOptionModel> parsedOptions = [];
if (json['options'] != null && json['options'] is List) {
for (var opt in json['options']) {
if (opt is Map) {
parsedOptions.add(SocraticOptionModel.fromJson(Map<String, dynamic>.from(opt)));
}
}
}
return SocraticCheckpointModel(
id: (json['id'] as num?)?.toInt() ?? 0,
questionText: json['question']?.toString() ?? json['question_text']?.toString() ?? 'سؤال فحص الفهم السقراطي',
timestampSeconds: (json['timestamp_seconds'] as num?)?.toInt() ?? 120,
rewindSecondsOnFail: (json['rewind_seconds'] as num?)?.toInt() ?? 45,
hint: json['hint']?.toString() ?? '',
pedagogicalExplanation: json['explanation']?.toString() ?? '',
options: parsedOptions,
);
}
}
/// Model representing a single choice option in a checkpoint
class SocraticOptionModel {
final int id;
final String text;
final bool isCorrect;
const SocraticOptionModel({
required this.id,
required this.text,
required this.isCorrect,
});
factory SocraticOptionModel.fromJson(Map<String, dynamic> json) {
return SocraticOptionModel(
id: (json['id'] as num?)?.toInt() ?? 0,
text: json['text']?.toString() ?? json['option_text']?.toString() ?? '',
isCorrect: (json['is_correct'] as bool?) ?? false,
);
}
}
/// Model for Lesson Playback Data (Streams, Versions, Chapters, Checkpoints)
class LessonPlaybackData {
final int lessonId;
final String title;
final int durationSeconds;
final String videoUrl;
final String storageType;
final List<LessonVersionModel> availableVersions;
final List<SocraticCheckpointModel> checkpoints;
const LessonPlaybackData({
required this.lessonId,
required this.title,
required this.durationSeconds,
required this.videoUrl,
this.storageType = 'api_upload',
this.availableVersions = const [],
this.checkpoints = const [],
});
factory LessonPlaybackData.fromJson(Map<String, dynamic> json) {
final lesson = json['lesson'] is Map ? json['lesson'] as Map : {};
final playback = json['playback'] is Map ? json['playback'] as Map : {};
// Parse versions
final List<LessonVersionModel> versions = [];
if (json['available_versions'] is List) {
for (var v in json['available_versions']) {
if (v is Map) {
versions.add(LessonVersionModel.fromJson(Map<String, dynamic>.from(v)));
}
}
}
// Parse checkpoints
final List<SocraticCheckpointModel> points = [];
if (json['checkpoints'] is List) {
for (var c in json['checkpoints']) {
if (c is Map) {
points.add(SocraticCheckpointModel.fromJson(Map<String, dynamic>.from(c)));
}
}
}
final vidUrl = playback['hls_url']?.toString() ??
playback['stream_url']?.toString() ??
playback['video_url']?.toString() ?? '';
return LessonPlaybackData(
lessonId: (lesson['id'] as num?)?.toInt() ?? 0,
title: lesson['title']?.toString() ?? 'الدرس التفاعلي',
durationSeconds: (lesson['duration_seconds'] as num?)?.toInt() ?? 0,
videoUrl: vidUrl,
storageType: playback['storage_type']?.toString() ?? 'api_upload',
availableVersions: versions,
checkpoints: points,
);
}
}
/// Model for Teacher vs AI Lesson versions
class LessonVersionModel {
final int lessonId;
final bool isAi;
final String teacherName;
final String schoolName;
final String label;
final bool isRecommended;
final String videoUrl;
const LessonVersionModel({
required this.lessonId,
required this.isAi,
required this.teacherName,
required this.schoolName,
required this.label,
required this.isRecommended,
required this.videoUrl,
});
factory LessonVersionModel.fromJson(Map<String, dynamic> json) {
final playback = json['playback'] is Map ? json['playback'] as Map : {};
final vidUrl = playback['hls_url']?.toString() ??
playback['stream_url']?.toString() ??
playback['video_url']?.toString() ?? '';
return LessonVersionModel(
lessonId: (json['lesson_id'] as num?)?.toInt() ?? 0,
isAi: (json['is_ai'] as bool?) ?? false,
teacherName: json['teacher_name']?.toString() ?? '',
schoolName: json['school_name']?.toString() ?? '',
label: json['label']?.toString() ?? 'شرح معتمد',
isRecommended: (json['is_recommended'] as bool?) ?? false,
videoUrl: vidUrl,
);
}
}