From 6ad43bf6a112105f9ae0baf5ec2c2095e9cbf170 Mon Sep 17 00:00:00 2001 From: syed-tp Date: Mon, 27 Jul 2026 16:26:49 +0530 Subject: [PATCH 1/4] fix: correct NAT question parsing and cache custom exam courses Updated QuestionDto to parse verbose string types like "NAT, Numerical Answer Type". This ensures numerical questions properly render as text inputs instead of options. Added keepAlive to CustomExamCourses provider to prevent redundant network fetches. --- packages/core/lib/data/models/question_dto.dart | 8 ++++++++ .../lib/providers/custom_exam_config_provider.g.dart | 2 +- .../lib/providers/custom_exam_courses_provider.dart | 2 +- .../lib/providers/custom_exam_courses_provider.g.dart | 9 +++------ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/core/lib/data/models/question_dto.dart b/packages/core/lib/data/models/question_dto.dart index d84ede1b7..83a9a3101 100644 --- a/packages/core/lib/data/models/question_dto.dart +++ b/packages/core/lib/data/models/question_dto.dart @@ -133,6 +133,14 @@ class QuestionDto { 'S' => 'shortAnswer', 'N' => 'numerical', 'E' => 'essay', + final String t when t.startsWith('NAT') || t.contains('Numerical') => + 'numerical', + final String t + when t.startsWith('MCQ') || t.contains('Multiple Choice') => + 'singleSelect', + final String t + when t.startsWith('MSQ') || t.contains('Multiple Select') => + 'multipleSelect', _ => 'singleSelect', }, subject: diff --git a/packages/exams/lib/providers/custom_exam_config_provider.g.dart b/packages/exams/lib/providers/custom_exam_config_provider.g.dart index 08aa807c1..de3ace91b 100644 --- a/packages/exams/lib/providers/custom_exam_config_provider.g.dart +++ b/packages/exams/lib/providers/custom_exam_config_provider.g.dart @@ -171,7 +171,7 @@ class _CustomExamConfigProviderElement } String _$customExamSelectionHash() => - r'b99393795bf607e6b6610bbaf9b2232d58ba513a'; + r'06e161fc44fa0f401cf64aa335e5516dff1f993a'; abstract class _$CustomExamSelection extends BuildlessAutoDisposeNotifier { diff --git a/packages/exams/lib/providers/custom_exam_courses_provider.dart b/packages/exams/lib/providers/custom_exam_courses_provider.dart index fb124fed9..78d93888e 100644 --- a/packages/exams/lib/providers/custom_exam_courses_provider.dart +++ b/packages/exams/lib/providers/custom_exam_courses_provider.dart @@ -4,7 +4,7 @@ import '../repositories/custom_exam_repository.dart'; part 'custom_exam_courses_provider.g.dart'; -@riverpod +@Riverpod(keepAlive: true) class CustomExamCourses extends _$CustomExamCourses { @override FutureOr> build() async { diff --git a/packages/exams/lib/providers/custom_exam_courses_provider.g.dart b/packages/exams/lib/providers/custom_exam_courses_provider.g.dart index 61334c43f..7a5dc123c 100644 --- a/packages/exams/lib/providers/custom_exam_courses_provider.g.dart +++ b/packages/exams/lib/providers/custom_exam_courses_provider.g.dart @@ -6,15 +6,12 @@ part of 'custom_exam_courses_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$customExamCoursesHash() => r'78f98f9280dde682376bc98faf87079f22e4d493'; +String _$customExamCoursesHash() => r'd01c972b5af42afd2876845a53882342995856d3'; /// See also [CustomExamCourses]. @ProviderFor(CustomExamCourses) final customExamCoursesProvider = - AutoDisposeAsyncNotifierProvider< - CustomExamCourses, - List - >.internal( + AsyncNotifierProvider>.internal( CustomExamCourses.new, name: r'customExamCoursesProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') @@ -24,6 +21,6 @@ final customExamCoursesProvider = allTransitiveDependencies: null, ); -typedef _$CustomExamCourses = AutoDisposeAsyncNotifier>; +typedef _$CustomExamCourses = AsyncNotifier>; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package From 61379590a398083553a76c1a59edfdf29b328181 Mon Sep 17 00:00:00 2001 From: syed-tp Date: Mon, 27 Jul 2026 17:01:26 +0530 Subject: [PATCH 2/4] refactor: update question type mapping logic and configure auto-dispose timer for custom exam provider --- .../core/lib/data/models/question_dto.dart | 6 +++--- .../test/data/models/question_dto_test.dart | 20 +++++++++++++++++++ .../custom_exam_courses_provider.dart | 9 ++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/core/lib/data/models/question_dto.dart b/packages/core/lib/data/models/question_dto.dart index 83a9a3101..3ee37b0ac 100644 --- a/packages/core/lib/data/models/question_dto.dart +++ b/packages/core/lib/data/models/question_dto.dart @@ -133,13 +133,13 @@ class QuestionDto { 'S' => 'shortAnswer', 'N' => 'numerical', 'E' => 'essay', - final String t when t.startsWith('NAT') || t.contains('Numerical') => + final String t when t.contains('Numerical') || t.contains('NAT') => 'numerical', final String t - when t.startsWith('MCQ') || t.contains('Multiple Choice') => + when t.contains('Multiple Choice') || t.contains('MCQ') => 'singleSelect', final String t - when t.startsWith('MSQ') || t.contains('Multiple Select') => + when t.contains('Multiple Select') || t.contains('MSQ') => 'multipleSelect', _ => 'singleSelect', }, diff --git a/packages/core/test/data/models/question_dto_test.dart b/packages/core/test/data/models/question_dto_test.dart index f227735ef..f174419c7 100644 --- a/packages/core/test/data/models/question_dto_test.dart +++ b/packages/core/test/data/models/question_dto_test.dart @@ -23,6 +23,26 @@ void main() { ); }, ); + + test('parses verbose string types correctly', () { + final natQuestion = QuestionDto.fromJson({ + 'id': '1', + 'type': 'NAT, Numerical Answer Type', + }); + expect(natQuestion.type, 'numerical'); + + final mcqQuestion = QuestionDto.fromJson({ + 'id': '2', + 'type': 'MCQ, Multiple Choice Type', + }); + expect(mcqQuestion.type, 'singleSelect'); + + final msqQuestion = QuestionDto.fromJson({ + 'id': '3', + 'type': 'MSQ, Multiple Select Type', + }); + expect(msqQuestion.type, 'multipleSelect'); + }); }); group('AnswerDto', () { diff --git a/packages/exams/lib/providers/custom_exam_courses_provider.dart b/packages/exams/lib/providers/custom_exam_courses_provider.dart index 78d93888e..de17baef8 100644 --- a/packages/exams/lib/providers/custom_exam_courses_provider.dart +++ b/packages/exams/lib/providers/custom_exam_courses_provider.dart @@ -1,13 +1,20 @@ +import 'dart:async'; import 'package:core/data/data.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import '../repositories/custom_exam_repository.dart'; part 'custom_exam_courses_provider.g.dart'; -@Riverpod(keepAlive: true) +@riverpod class CustomExamCourses extends _$CustomExamCourses { @override FutureOr> build() async { + final link = ref.keepAlive(); + final timer = Timer(const Duration(minutes: 5), () { + link.close(); + }); + ref.onDispose(() => timer.cancel()); + final repository = ref.watch(customExamRepositoryProvider); // Fetch courses with allow_custom_test=true From 9dee2a02199ed1d7d64aa4b2ac117cdff2e87a0f Mon Sep 17 00:00:00 2001 From: syed-tp Date: Mon, 27 Jul 2026 17:18:24 +0530 Subject: [PATCH 3/4] refactor: convert CustomExamCourses provider to AutoDisposeAsyncNotifier --- .../lib/providers/custom_exam_courses_provider.g.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/exams/lib/providers/custom_exam_courses_provider.g.dart b/packages/exams/lib/providers/custom_exam_courses_provider.g.dart index 7a5dc123c..ad6ea6fd9 100644 --- a/packages/exams/lib/providers/custom_exam_courses_provider.g.dart +++ b/packages/exams/lib/providers/custom_exam_courses_provider.g.dart @@ -6,12 +6,15 @@ part of 'custom_exam_courses_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$customExamCoursesHash() => r'd01c972b5af42afd2876845a53882342995856d3'; +String _$customExamCoursesHash() => r'd427e1dffa61913929a124719db640ff7138e9ff'; /// See also [CustomExamCourses]. @ProviderFor(CustomExamCourses) final customExamCoursesProvider = - AsyncNotifierProvider>.internal( + AutoDisposeAsyncNotifierProvider< + CustomExamCourses, + List + >.internal( CustomExamCourses.new, name: r'customExamCoursesProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') @@ -21,6 +24,6 @@ final customExamCoursesProvider = allTransitiveDependencies: null, ); -typedef _$CustomExamCourses = AsyncNotifier>; +typedef _$CustomExamCourses = AutoDisposeAsyncNotifier>; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package From 0b279513323d652595c5890effcfb85663d6d688 Mon Sep 17 00:00:00 2001 From: syed-tp Date: Mon, 27 Jul 2026 17:19:42 +0530 Subject: [PATCH 4/4] chore: drop stray diff from custom_exam_config_provider.g.dart --- packages/exams/lib/providers/custom_exam_config_provider.g.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/exams/lib/providers/custom_exam_config_provider.g.dart b/packages/exams/lib/providers/custom_exam_config_provider.g.dart index de3ace91b..08aa807c1 100644 --- a/packages/exams/lib/providers/custom_exam_config_provider.g.dart +++ b/packages/exams/lib/providers/custom_exam_config_provider.g.dart @@ -171,7 +171,7 @@ class _CustomExamConfigProviderElement } String _$customExamSelectionHash() => - r'06e161fc44fa0f401cf64aa335e5516dff1f993a'; + r'b99393795bf607e6b6610bbaf9b2232d58ba513a'; abstract class _$CustomExamSelection extends BuildlessAutoDisposeNotifier {