From 25ddceac7b0fe88004f5bb394933dda573d25d11 Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:17:51 -0500 Subject: [PATCH] group together 'other' category with more specific categories (#1026) --- .../analytics/construct_list_model.dart | 77 +++++++++++++++---- .../models/analytics/construct_use_model.dart | 2 +- .../models/analytics/constructs_model.dart | 4 +- .../practice_activity_model.dart | 10 ++- .../utils/grammar/get_grammar_copy.dart | 2 +- .../analytics_popup/analytics_popup.dart | 6 +- 6 files changed, 74 insertions(+), 27 deletions(-) diff --git a/lib/pangea/models/analytics/construct_list_model.dart b/lib/pangea/models/analytics/construct_list_model.dart index bcf676db3..b82ca6cb2 100644 --- a/lib/pangea/models/analytics/construct_list_model.dart +++ b/lib/pangea/models/analytics/construct_list_model.dart @@ -63,14 +63,49 @@ class ConstructListModel { /// key = lemmma + constructType.string, value = ConstructUses void _updateConstructMap(final List newUses) { for (final use in newUses) { - final currentUses = _constructMap[use.identifier.string] ?? - ConstructUses( + ConstructUses? currentUses; + if (use.category.toLowerCase() == "other") { + final specificKey = _constructMap.keys.firstWhereOrNull( + (key) => key.startsWith(use.identifier.partialString), + ); + + if (specificKey != null) { + currentUses = _constructMap[specificKey]; + use.category = currentUses!.category; + } else if (_constructMap.containsKey(use.identifier.string)) { + currentUses = _constructMap[use.identifier.string]; + } else { + currentUses = ConstructUses( uses: [], constructType: use.constructType, lemma: use.lemma, category: use.category, ); - currentUses.uses.add(use); + } + } else { + final broadKey = _constructMap.keys.firstWhereOrNull( + (key) => + key.startsWith(use.identifier.partialString) && + key.toLowerCase().endsWith("other"), + ); + + if (broadKey != null) { + currentUses = _constructMap[broadKey]; + for (final broadUse in currentUses!.uses) { + broadUse.category = use.category; + } + _constructMap.remove(broadKey); + } else { + currentUses = _constructMap[use.identifier.string] ?? + ConstructUses( + uses: [], + constructType: use.constructType, + lemma: use.lemma, + category: use.category, + ); + } + } + currentUses!.uses.add(use); currentUses.setLastUsed(use.timeStamp); _constructMap[use.identifier.string] = currentUses; } @@ -127,28 +162,38 @@ class ConstructListModel { } } - ConstructUses? getConstructUses(ConstructIdentifier identifier) { - final partialKey = "${identifier.lemma}-${identifier.type.string}"; + ConstructUses? _getPartialSpecificMatch(ConstructIdentifier identifier) { + return _constructMap.entries + .firstWhereOrNull( + (entry) => + entry.key.startsWith(identifier.partialString) && + !entry.key.toLowerCase().endsWith("other"), + ) + ?.value; + } + + ConstructUses? _getPartialBroadMatch(ConstructIdentifier identifier) { + return _constructMap.entries + .firstWhereOrNull( + (entry) => + entry.key.startsWith(identifier.partialString) && + entry.key.toLowerCase().endsWith("other"), + ) + ?.value; + } + ConstructUses? getConstructUses(ConstructIdentifier identifier) { if (_constructMap.containsKey(identifier.string)) { // try to get construct use entry with full ID key return _constructMap[identifier.string]; - } else if (identifier.category.toLowerCase() == "other") { + } else if (identifier.isOther) { // if the category passed to this function is "other", return the first // construct use entry that starts with the partial key - return _constructMap.entries - .firstWhereOrNull((entry) => entry.key.startsWith(partialKey)) - ?.value; + return _getPartialSpecificMatch(identifier); } else { // if the category passed to this function is not "other", return the first // construct use entry that starts with the partial key and ends with "other" - return _constructMap.entries - .firstWhereOrNull( - (entry) => - entry.key.startsWith(partialKey) && - entry.key.toLowerCase().endsWith("other"), - ) - ?.value; + return _getPartialBroadMatch(identifier); } } diff --git a/lib/pangea/models/analytics/construct_use_model.dart b/lib/pangea/models/analytics/construct_use_model.dart index 09195ecba..ce9a1658d 100644 --- a/lib/pangea/models/analytics/construct_use_model.dart +++ b/lib/pangea/models/analytics/construct_use_model.dart @@ -39,7 +39,7 @@ class ConstructUses { _lastUsed = time; } - String get category => _category ?? "Other"; + String get category => _category ?? "other"; ConstructIdentifier get id => ConstructIdentifier( lemma: lemma, diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index 1a9118838..16c6d62df 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -134,7 +134,7 @@ class OneConstructUse { : categoryEntry is List && categoryEntry.isNotEmpty ? categoryEntry.first : null; - return category ?? "Other"; + return category ?? "other"; } if (categoryEntry == null) { @@ -168,7 +168,7 @@ class OneConstructUse { ErrorHandler.logError( m: "Morph construct lemma $morphLemma not found in morph categories and labels", ); - return "Other"; + return "other"; } Room? getRoom(Client client) { diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart index d871e0836..1502a7066 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -62,9 +62,7 @@ class ConstructIdentifier { return other is ConstructIdentifier && other.lemma == lemma && other.type == type && - (category == other.category || - category.toLowerCase() == "other" || - other.category.toLowerCase() == "other"); + (category == other.category || isOther || other.isOther); } @override @@ -73,7 +71,11 @@ class ConstructIdentifier { } String get string => - "$lemma-${type.string}${category != "" ? "-$category" : "-other"}"; + "$partialString${category != "" ? "-$category" : "-other"}".toLowerCase(); + + String get partialString => "$lemma:${type.string}".toLowerCase(); + + bool get isOther => category.toLowerCase() == "other"; } class CandidateMessage { diff --git a/lib/pangea/utils/grammar/get_grammar_copy.dart b/lib/pangea/utils/grammar/get_grammar_copy.dart index b8e406faf..af13fa065 100644 --- a/lib/pangea/utils/grammar/get_grammar_copy.dart +++ b/lib/pangea/utils/grammar/get_grammar_copy.dart @@ -15,7 +15,7 @@ String? getGrammarCopy({ required String lemma, required BuildContext context, }) { - if (category.toLowerCase() == 'other') { + if (category.toLowerCase() == "other") { return null; } diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart index 4fae8c71c..cebfd18ea 100644 --- a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup/analytics_popup.dart @@ -34,8 +34,8 @@ class AnalyticsPopupState extends State { // Sort the list with custom logic entries.sort((a, b) { // Check if one of the keys is 'Other' - if (a.key == 'Other') return 1; - if (b.key == 'Other') return -1; + if (a.key.toLowerCase() == "other") return 1; + if (b.key.toLowerCase() == "other") return -1; // Sort by the length of the list in descending order final aTotalPoints = a.value.fold( @@ -73,7 +73,7 @@ class AnalyticsPopupState extends State { final bool hasNoData = _constructsModel.constructList(type: widget.type).isEmpty; final bool hasNoCategories = _categoriesToUses.length == 1 && - _categoriesToUses.entries.first.key == "Other"; + _categoriesToUses.entries.first.key.toLowerCase() == "other"; if (selectedCategory != null) { dialogContent = Column(