fix(emoji_activity_generator): ensure unique choices
This commit is contained in:
parent
3acab885d9
commit
868669484a
4 changed files with 81 additions and 50 deletions
|
|
@ -1,9 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_form.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_choice.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PracticeMatchActivity {
|
||||
/// The constructIdenfifiers involved in the activity
|
||||
|
|
@ -20,35 +19,50 @@ class PracticeMatchActivity {
|
|||
'Construct: ${ith.key}, Forms: ${ith.value}',
|
||||
);
|
||||
}
|
||||
// if there are multiple forms for a construct, pick one to display
|
||||
// each cosntruct will have ~3 forms
|
||||
// sometimes a form could be in multiple constructs
|
||||
// so we need to make sure we don't display the same form twice
|
||||
// if we get to one that is already displayed, we can pick a different form
|
||||
// either from that construct's options, or returning to the previous construct
|
||||
// and picking a different form from there
|
||||
// for all the entries in matchInfo, remove an Strings that appear in multiple entries
|
||||
final Map<String, int> allForms = {};
|
||||
for (final ith in matchInfo.entries) {
|
||||
for (int i = 0; i < ith.value.length; i++) {
|
||||
final String acceptableAnswer = ith.value[i];
|
||||
if (!choices
|
||||
.any((element) => element.choiceContent == acceptableAnswer)) {
|
||||
choices.add(
|
||||
PracticeChoice(choiceContent: acceptableAnswer, form: ith.key),
|
||||
);
|
||||
debugPrint(
|
||||
'Added choice: ${choices.last.choiceContent} for form: ${choices.last.form.form}',
|
||||
);
|
||||
i = ith.value.length; // break out of the loop
|
||||
for (final form in ith.value) {
|
||||
if (allForms.containsKey(form)) {
|
||||
allForms[form] = allForms[form]! + 1;
|
||||
} else {
|
||||
allForms[form] = 1;
|
||||
}
|
||||
// TODO: if none found, we can probably pick a different form for the other one
|
||||
}
|
||||
}
|
||||
|
||||
// remove any items from matchInfo that don't have an item in choices
|
||||
for (final ith in matchInfo.keys) {
|
||||
if (!choices.any((choice) => choice.form == ith)) {
|
||||
matchInfo.remove(ith);
|
||||
for (final ith in matchInfo.entries) {
|
||||
if (ith.value.isEmpty) {
|
||||
matchInfo.remove(ith.key);
|
||||
continue;
|
||||
}
|
||||
choices.add(
|
||||
PracticeChoice(
|
||||
choiceContent: ith.value.firstWhere(
|
||||
(element) => allForms[element] == 1,
|
||||
orElse: () {
|
||||
ErrorHandler.logError(
|
||||
m: "no unique emoji for construct",
|
||||
data: {
|
||||
'construct': ith.key,
|
||||
'forms': ith.value,
|
||||
"practice_match": toJson(),
|
||||
},
|
||||
);
|
||||
final String first = ith.value.first;
|
||||
// remove the element from the other entry to avoid duplicates
|
||||
for (final ith in matchInfo.entries) {
|
||||
ith.value.removeWhere((choice) => choice == first);
|
||||
}
|
||||
return ith.value.first;
|
||||
},
|
||||
),
|
||||
form: ith.key,
|
||||
),
|
||||
);
|
||||
debugPrint(
|
||||
'Added PracticeChoice Construct: ${ith.key}, Forms: ${ith.value}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart';
|
||||
import 'package:fluffychat/pangea/lemmas/lemma_info_response.dart';
|
||||
|
|
@ -12,6 +9,7 @@ import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
|
|||
import 'package:fluffychat/pangea/practice_activities/practice_selection_repo.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_target.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class PracticeSelection {
|
||||
late String _userL2;
|
||||
|
|
@ -41,7 +39,8 @@ class PracticeSelection {
|
|||
List<PangeaToken> get tokens => _tokens;
|
||||
|
||||
bool get eligibleForPractice =>
|
||||
_tokens.any((t) => t.lemma.saveVocab) && langCode == _userL2;
|
||||
_tokens.any((t) => t.lemma.saveVocab) &&
|
||||
langCode.split("-")[0] == _userL2.split("-")[0];
|
||||
|
||||
String get messageText => PangeaToken.reconstructText(tokens);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/practice_selection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_storage/get_storage.dart';
|
||||
|
||||
class PracticeSelectionRepo {
|
||||
static final GetStorage _storage = GetStorage('practice_selection_cache');
|
||||
|
|
@ -21,18 +20,39 @@ class PracticeSelectionRepo {
|
|||
_memoryCache[key] = entry;
|
||||
}
|
||||
|
||||
static MapEntry<String, PracticeSelection>? _parsePracticeSelection(
|
||||
String key) {
|
||||
if (!_storage.hasData(key)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final entry = PracticeSelection.fromJson(_storage.read(key));
|
||||
return MapEntry(key, entry);
|
||||
} catch (e, s) {
|
||||
ErrorHandler.logError(
|
||||
m: 'Failed to parse PracticeSelection from JSON',
|
||||
e: e,
|
||||
s: s,
|
||||
data: {
|
||||
'key': key,
|
||||
'json': _storage.read(key),
|
||||
},
|
||||
);
|
||||
_storage.remove(key);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static void clean() {
|
||||
final Iterable<String> keys = _storage.getKeys();
|
||||
if (keys.length > 300) {
|
||||
final entries = keys
|
||||
.map((key) {
|
||||
final entry = PracticeSelection.fromJson(_storage.read(key));
|
||||
return MapEntry(key, entry);
|
||||
})
|
||||
.map((key) => _parsePracticeSelection(key))
|
||||
.where((entry) => entry != null)
|
||||
.cast<MapEntry<String, PracticeSelection>>()
|
||||
.toList()
|
||||
..sort((a, b) => a.value.createdAt.compareTo(b.value.createdAt));
|
||||
for (var i = 0; i < 5; i++) {
|
||||
for (var i = 0; i < 5 && i < entries.length; i++) {
|
||||
_storage.remove(entries[i].key);
|
||||
}
|
||||
}
|
||||
|
|
@ -53,9 +73,9 @@ class PracticeSelectionRepo {
|
|||
return _memoryCache[key];
|
||||
}
|
||||
|
||||
final entryJson = _storage.read(key);
|
||||
if (entryJson != null) {
|
||||
final entry = PracticeSelection.fromJson(entryJson);
|
||||
final stored = _parsePracticeSelection(key);
|
||||
if (stored != null) {
|
||||
final entry = stored.value;
|
||||
if (DateTime.now().difference(entry.createdAt).inDays > 1) {
|
||||
debugPrint('removing old entry ${entry.createdAt}');
|
||||
_storage.remove(key);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
|
@ -31,6 +25,10 @@ import 'package:fluffychat/pangea/toolbar/reading_assistance_input_row/morph_sel
|
|||
import 'package:fluffychat/pangea/toolbar/widgets/message_selection_positioner.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/widgets/reading_assistance_content.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
/// Controls data at the top level of the toolbar (mainly token / toolbar mode selection)
|
||||
class MessageSelectionOverlay extends StatefulWidget {
|
||||
|
|
@ -423,8 +421,8 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
: null;
|
||||
|
||||
bool get messageInUserL2 =>
|
||||
pangeaMessageEvent?.messageDisplayLangCode ==
|
||||
MatrixState.pangeaController.languageController.userL2?.langCode;
|
||||
pangeaMessageEvent?.messageDisplayLangCode.split("-")[0] ==
|
||||
MatrixState.pangeaController.languageController.userL2?.langCodeShort;
|
||||
|
||||
PangeaToken? get selectedToken =>
|
||||
pangeaMessageEvent?.messageDisplayRepresentation?.tokens
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue