diff --git a/lib/pangea/controllers/language_list_controller.dart b/lib/pangea/controllers/language_list_controller.dart index 31e4513fa..77f4ae9e2 100644 --- a/lib/pangea/controllers/language_list_controller.dart +++ b/lib/pangea/controllers/language_list_controller.dart @@ -93,7 +93,6 @@ class PangeaLanguage { } static LanguageModel byLangCode(String langCode) { - final list = _langList; for (final element in _langList) { if (element.langCode == langCode) return element; } diff --git a/lib/pangea/enum/activity_display_instructions_enum.dart b/lib/pangea/enum/activity_display_instructions_enum.dart new file mode 100644 index 000000000..9a96d669c --- /dev/null +++ b/lib/pangea/enum/activity_display_instructions_enum.dart @@ -0,0 +1,13 @@ +enum ActivityDisplayInstructionsEnum { highlight, hide } + +extension ActivityDisplayInstructionsEnumExt + on ActivityDisplayInstructionsEnum { + String get string { + switch (this) { + case ActivityDisplayInstructionsEnum.highlight: + return 'highlight'; + case ActivityDisplayInstructionsEnum.hide: + return 'hide'; + } + } +} diff --git a/lib/pangea/models/pangea_token_model.dart b/lib/pangea/models/pangea_token_model.dart index 7055c29fa..608d5b9d1 100644 --- a/lib/pangea/models/pangea_token_model.dart +++ b/lib/pangea/models/pangea_token_model.dart @@ -24,17 +24,19 @@ class PangeaToken { required this.morph, }); - static _getLemmas(String text, dynamic json) { + static Lemma _getLemmas(String text, dynamic json) { if (json != null) { // July 24, 2024 - we're changing from a list to a single lemma and this is for backwards compatibility // previously sent tokens have lists of lemmas if (json is Iterable) { return json - .map( - (e) => Lemma.fromJson(e as Map), - ) - .toList() - .cast(); + .map( + (e) => Lemma.fromJson(e as Map), + ) + .toList() + .cast() + .firstOrNull ?? + Lemma(text: text, saveVocab: false, form: text); } else { return Lemma.fromJson(json); } @@ -61,6 +63,8 @@ class PangeaToken { Map toJson() => { _textKey: text.toJson(), _lemmaKey: lemma.toJson(), + 'pos': pos, + 'morph': morph, }; int get end => text.offset + text.length; diff --git a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart index 68376d410..18302bd43 100644 --- a/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart @@ -1,15 +1,18 @@ import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:flutter/material.dart'; class MultipleChoice { final String question; final List choices; final String answer; + final RelevantSpanDisplayDetails? spanDisplayDetails; MultipleChoice({ required this.question, required this.choices, required this.answer, + this.spanDisplayDetails, }); bool isCorrect(int index) => index == correctAnswerIndex; @@ -28,6 +31,9 @@ class MultipleChoice { question: json['question'] as String, choices: (json['choices'] as List).map((e) => e as String).toList(), answer: json['answer'] ?? json['correct_answer'] as String, + spanDisplayDetails: json['span_display_details'] != null + ? RelevantSpanDisplayDetails.fromJson(json['span_display_details']) + : null, ); } @@ -36,6 +42,7 @@ class MultipleChoice { 'question': question, 'choices': choices, 'answer': answer, + 'span_display_details': spanDisplayDetails, }; } } 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 fa3e25acf..645d550e5 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -1,5 +1,7 @@ import 'dart:developer'; +import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/enum/activity_display_instructions_enum.dart'; import 'package:fluffychat/pangea/enum/activity_type_enum.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart'; @@ -279,4 +281,58 @@ class PracticeActivityModel { 'free_response': freeResponse?.toJson(), }; } + + RelevantSpanDisplayDetails? getRelevantSpanDisplayDetails() { + switch (activityType) { + case ActivityTypeEnum.multipleChoice: + return multipleChoice?.spanDisplayDetails; + case ActivityTypeEnum.listening: + return null; + case ActivityTypeEnum.speaking: + return null; + case ActivityTypeEnum.freeResponse: + return null; + default: + debugger(when: kDebugMode); + return null; + } + } +} + +/// For those activities with a relevant span, this class will hold the details +/// of the span and how it should be displayed +/// e.g. hide the span for conjugation activities +class RelevantSpanDisplayDetails { + final int offset; + final int length; + final ActivityDisplayInstructionsEnum displayInstructions; + + RelevantSpanDisplayDetails({ + required this.offset, + required this.length, + required this.displayInstructions, + }); + + factory RelevantSpanDisplayDetails.fromJson(Map json) { + final ActivityDisplayInstructionsEnum? display = + ActivityDisplayInstructionsEnum.values.firstWhereOrNull( + (e) => e.string == json['display_instructions'], + ); + if (display == null) { + debugger(when: kDebugMode); + } + return RelevantSpanDisplayDetails( + offset: json['offset'] as int, + length: json['length'] as int, + displayInstructions: display ?? ActivityDisplayInstructionsEnum.hide, + ); + } + + Map toJson() { + return { + 'offset': offset, + 'length': length, + 'display_instructions': displayInstructions, + }; + } }