From 5f540e9d16e83475c593340f39ac2856ddea3aa8 Mon Sep 17 00:00:00 2001 From: Ava Shilling <165050625+avashilling@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:30:16 -0500 Subject: [PATCH] chore: ensure grammar category has example and multiple choices --- .../analytics_practice_page.dart | 3 +- .../analytics_practice_session_repo.dart | 50 ++++++++++++++++--- .../analytics_practice_view.dart | 3 +- .../practice_activities/practice_target.dart | 5 ++ 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/lib/pangea/analytics_practice/analytics_practice_page.dart b/lib/pangea/analytics_practice/analytics_practice_page.dart index 44b471f92..4f88cd84a 100644 --- a/lib/pangea/analytics_practice/analytics_practice_page.dart +++ b/lib/pangea/analytics_practice/analytics_practice_page.dart @@ -535,8 +535,7 @@ class AnalyticsPracticeState extends State String? form; if (widget.type == ConstructTypeEnum.morph) { - if (target.morphFeature == null) return null; - form = token.lemma.form; + return target.exampleMessage; } return ExampleMessageUtil.getExampleMessage( diff --git a/lib/pangea/analytics_practice/analytics_practice_session_repo.dart b/lib/pangea/analytics_practice/analytics_practice_session_repo.dart index c2c507741..9117c0d16 100644 --- a/lib/pangea/analytics_practice/analytics_practice_session_repo.dart +++ b/lib/pangea/analytics_practice/analytics_practice_session_repo.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/analytics_misc/example_message_util.dart'; import 'package:fluffychat/pangea/analytics_practice/analytics_practice_constants.dart'; import 'package:fluffychat/pangea/analytics_practice/analytics_practice_session_model.dart'; import 'package:fluffychat/pangea/common/network/requests.dart'; @@ -63,15 +64,16 @@ class AnalyticsPracticeSessionRepo { final remainingCount = (AnalyticsPracticeConstants.practiceGroupSize + AnalyticsPracticeConstants.errorBufferSize) - targets.length; - final morphEntries = morphs.entries.take(remainingCount); + final morphEntries = morphs.take(remainingCount); for (final entry in morphEntries) { targets.add( AnalyticsActivityTarget( target: PracticeTarget( - tokens: [entry.key], + tokens: [entry.token], activityType: ActivityTypeEnum.grammarCategory, - morphFeature: entry.value, + morphFeature: entry.feature, + exampleMessage: entry.exampleMessage, ), ), ); @@ -125,7 +127,7 @@ class AnalyticsPracticeSessionRepo { return targets; } - static Future> _fetchMorphs() async { + static Future> _fetchMorphs() async { final constructs = await MatrixState .pangeaController.matrixState.analyticsDataService .getAggregatedConstructs(ConstructTypeEnum.morph) @@ -141,7 +143,7 @@ class AnalyticsPracticeSessionRepo { return dateA.compareTo(dateB); }); - final targets = {}; + final targets = []; final Set seenForms = {}; for (final entry in constructs) { @@ -152,7 +154,12 @@ class AnalyticsPracticeSessionRepo { } final feature = MorphFeaturesEnumExtension.fromString(entry.id.category); - if (feature == MorphFeaturesEnum.Unknown) { + List? exampleMessage; + // Skip single option features + if (feature == MorphFeaturesEnum.Unknown || + feature == MorphFeaturesEnum.Poss || + feature == MorphFeaturesEnum.Reflex || + feature == MorphFeaturesEnum.PrepCase) { continue; } @@ -169,6 +176,17 @@ class AnalyticsPracticeSessionRepo { continue; } + exampleMessage = await ExampleMessageUtil.getExampleMessage( + await MatrixState.pangeaController.matrixState.analyticsDataService + .getConstructUse(entry.id), + MatrixState.pangeaController.matrixState.client, + form: form, + ); + + if (exampleMessage == null) { + continue; + } + seenForms.add(form); final token = PangeaToken( lemma: Lemma( @@ -180,7 +198,13 @@ class AnalyticsPracticeSessionRepo { pos: 'other', morph: {feature: use.lemma}, ); - targets[token] = feature; + targets.add( + MorphPracticeTarget( + feature: feature, + token: token, + exampleMessage: exampleMessage, + ), + ); break; } } @@ -312,3 +336,15 @@ class AnalyticsPracticeSessionRepo { return targets; } } + +class MorphPracticeTarget { + final PangeaToken token; + final MorphFeaturesEnum feature; + final List? exampleMessage; + + MorphPracticeTarget({ + required this.token, + required this.feature, + this.exampleMessage, + }); +} diff --git a/lib/pangea/analytics_practice/analytics_practice_view.dart b/lib/pangea/analytics_practice/analytics_practice_view.dart index 62acdd835..2724a191b 100644 --- a/lib/pangea/analytics_practice/analytics_practice_view.dart +++ b/lib/pangea/analytics_practice/analytics_practice_view.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; @@ -23,7 +25,6 @@ import 'package:fluffychat/pangea/practice_activities/practice_activity_model.da import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; class AnalyticsPracticeView extends StatelessWidget { final AnalyticsPracticeState controller; diff --git a/lib/pangea/practice_activities/practice_target.dart b/lib/pangea/practice_activities/practice_target.dart index 87c1ce7e7..93778c1b4 100644 --- a/lib/pangea/practice_activities/practice_target.dart +++ b/lib/pangea/practice_activities/practice_target.dart @@ -1,4 +1,5 @@ import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; @@ -24,10 +25,14 @@ class PracticeTarget { /// this is only defined for morphId activities final MorphFeaturesEnum? morphFeature; + /// Generated example message for the target, if applicable + final List? exampleMessage; + PracticeTarget({ required this.tokens, required this.activityType, this.morphFeature, + this.exampleMessage, }) { if (ActivityTypeEnum.morphId == activityType && morphFeature == null) { throw Exception("morphFeature must be defined for morphId activities");