Skip to content

Commit

Permalink
feat: moving to lemma def over contextual translation
Browse files Browse the repository at this point in the history
  • Loading branch information
wcjord committed Dec 30, 2024
1 parent 0368ce3 commit f626d5f
Show file tree
Hide file tree
Showing 14 changed files with 302 additions and 302 deletions.
53 changes: 53 additions & 0 deletions lib/pangea/constants/morph_categories_and_labels.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import 'dart:developer';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/symbols.dart';

const Map<String, List<String>> morphCategoriesAndLabels = {
"Pos": [
"ADJ",
Expand Down Expand Up @@ -165,3 +171,50 @@ const Map<String, List<String>> morphCategoriesAndLabels = {
"Voice": ["Act", "Mid", "Pass", "Antip", "Cau", "Dir", "Inv", "Rcp", "Caus"],
"X": ["X"],
};

// TODO Use the icons that Khue is creating
IconData getIconForMorphFeature(String feature) {
// Define a function to get the icon based on the universal dependency morphological feature (key)
switch (feature.toLowerCase()) {
case 'number':
// google material 123 icon
return Icons.format_list_numbered;
case 'gender':
return Icons.wc;
case 'tense':
return Icons.access_time;
case 'mood':
return Icons.mood;
case 'person':
return Icons.person;
case 'case':
return Icons.format_list_bulleted;
case 'degree':
return Icons.trending_up;
case 'verbform':
return Icons.text_format;
case 'voice':
return Icons.record_voice_over;
case 'aspect':
return Icons.aspect_ratio;
case 'prontype':
return Icons.text_fields;
case 'numtype':
return Icons.format_list_numbered;
case 'poss':
return Icons.account_balance;
case 'reflex':
return Icons.refresh;
case 'foreign':
return Icons.language;
case 'abbr':
return Icons.text_format;
case 'nountype':
return Symbols.abc;
case 'pos':
return Symbols.toys_and_games;
default:
debugger(when: kDebugMode);
return Icons.help_outline;
}
}
3 changes: 3 additions & 0 deletions lib/pangea/enum/morphs_enum.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// this should be an enum eventually though we're using a class for now

class Morphs {}
5 changes: 3 additions & 2 deletions lib/pangea/models/analytics/construct_list_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,13 @@ class ConstructListModel {
final List<ConstructUses> morphConstructs = constructList(
type: ConstructTypeEnum.morph,
);

final List<String> possibleDistractors = morphConstructs
.where(
(c) =>
c.category == morphFeature.toLowerCase() &&
c.lemma.toLowerCase() != morphTag.toLowerCase(),
c.lemma.toLowerCase() != morphTag.toLowerCase() &&
c.lemma.isNotEmpty &&
c.lemma != "X",
)
.map((c) => c.lemma)
.toList();
Expand Down
11 changes: 7 additions & 4 deletions lib/pangea/models/pangea_token_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ class PangeaToken {
}
}

bool get shouldDoPosActivity => shouldDoMorphActivity("Pos");
bool get shouldDoPosActivity => shouldDoMorphActivity("pos");

bool shouldDoMorphActivity(String feature) {
return shouldDoActivity(
Expand Down Expand Up @@ -582,11 +582,14 @@ class PangeaToken {
}

String get xpEmoji {
if (xp < 5) {
if (xp < 30) {
// bean emoji
return "🫛";
} else if (xp < 100) {
// sprout emoji
return "🌱";
} else if (xp < 10) {
return "🌿";
} else {
// flower emoji
return "🌺";
}
}
Expand Down
17 changes: 17 additions & 0 deletions lib/pangea/repo/lemma_definition_repo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,23 @@ class LemmaDictionaryRepo {
return response;
}

/// From the cache, get a random set of cached definitions that are not for a specific lemma
static List<String> getDistractorDefinitions(
LemmaDefinitionRequest req, int count) {
_clearExpiredEntries();

final List<String> definitions = [];
for (final entry in _cache.entries) {
if (entry.key.lemma != req.lemma) {
definitions.add(entry.value.definition);
}
}

definitions.shuffle();

return definitions.take(count).toList();
}

static void _clearExpiredEntries() {
final now = DateTime.now();
final expiredKeys = _cacheTimestamps.entries
Expand Down
9 changes: 6 additions & 3 deletions lib/pangea/repo/practice/morph_activity_generator.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:developer';

import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
import 'package:fluffychat/pangea/enum/analytics/morph_categories_enum.dart';
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/message_activity_request.dart';
Expand Down Expand Up @@ -30,14 +31,15 @@ class MorphActivityGenerator {
"SCONJ": [],
"PUNCT": [],
"VERB": ["Tense", "Aspect"],
"X": [],
},
};

/// Get the sequence of activities for a given part of speech
/// The sequence is a list of morphological features that should be practiced
/// in order for the given part of speech
Future<POSActivitySequence> getSequence(String langCode, String pos) async {
if (!sequence.containsKey(langCode)) {
POSActivitySequence getSequence(String? langCode, String pos) {
if (langCode == null || !sequence.containsKey(langCode)) {
langCode = "en";
}
final MorphActivitySequence morphActivitySequence = sequence[langCode]!;
Expand Down Expand Up @@ -89,7 +91,8 @@ class MorphActivityGenerator {
langCode: req.userL2,
activityType: ActivityTypeEnum.morphId,
content: ActivityContent(
question: "",
question:
"${getMorphologicalCategoryCopy(morphFeature, MatrixState.pangeaController.matrixState.context) ?? ""}?",
choices: distractors + [morphTag],
answers: [morphTag],
spanDisplayDetails: null,
Expand Down
13 changes: 7 additions & 6 deletions lib/pangea/repo/practice/practice_repo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:fluffychat/pangea/network/urls.dart';
import 'package:fluffychat/pangea/repo/practice/emoji_activity_generator.dart';
import 'package:fluffychat/pangea/repo/practice/lemma_activity_generator.dart';
import 'package:fluffychat/pangea/repo/practice/morph_activity_generator.dart';
import 'package:fluffychat/pangea/repo/practice/word_meaning_activity_generator.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
Expand All @@ -40,9 +41,10 @@ class PracticeGenerationController {

late PangeaController _pangeaController;

final MorphActivityGenerator _morph = MorphActivityGenerator();
final EmojiActivityGenerator _emoji = EmojiActivityGenerator();
final LemmaActivityGenerator _lemma = LemmaActivityGenerator();
final _morph = MorphActivityGenerator();
final _emoji = EmojiActivityGenerator();
final _lemma = LemmaActivityGenerator();
final _wordMeaning = WordMeaningActivityGenerator();

PracticeGenerationController() {
_pangeaController = MatrixState.pangeaController;
Expand Down Expand Up @@ -126,10 +128,9 @@ class PracticeGenerationController {
return _lemma.get(req);
case ActivityTypeEnum.morphId:
return _morph.get(req);
case ActivityTypeEnum.wordFocusListening:
// TODO bring clientside because more efficient
case ActivityTypeEnum.wordMeaning:
// TODO get correct answer with translation and distractors with distractor service
return _wordMeaning.get(req);
case ActivityTypeEnum.wordFocusListening:
case ActivityTypeEnum.hiddenWordListening:
return _fetchFromServer(
accessToken: accessToken,
Expand Down
47 changes: 47 additions & 0 deletions lib/pangea/repo/practice/word_meaning_activity_generator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
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/message_activity_request.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart';
import 'package:fluffychat/pangea/repo/lemma_definition_repo.dart';

class WordMeaningActivityGenerator {
Future<MessageActivityResponse> get(
MessageActivityRequest req,
) async {
final ConstructIdentifier lemmaId = ConstructIdentifier(
lemma: req.targetTokens[0].lemma.text,
type: ConstructTypeEnum.vocab,
category: req.targetTokens[0].pos,
);

final LemmaDefinitionRequest lemmaDefReq = LemmaDefinitionRequest(
lemma: lemmaId.lemma,
partOfSpeech: lemmaId.category,

/// This assumes that the user's L2 is the language of the lemma
lemmaLang: req.userL2,
userL1: req.userL1,
);

final res = await LemmaDictionaryRepo.get(lemmaDefReq);

final choices =
LemmaDictionaryRepo.getDistractorDefinitions(lemmaDefReq, 3);

return MessageActivityResponse(
activity: PracticeActivityModel(
tgtConstructs: [lemmaId],
targetTokens: req.targetTokens,
langCode: req.userL2,
activityType: ActivityTypeEnum.wordMeaning,
content: ActivityContent(
question: "?",
choices: choices,
answers: [res.definition],
spanDisplayDetails: null,
),
),
);
}
}
38 changes: 19 additions & 19 deletions lib/pangea/widgets/practice_activity/emoji_practice_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,32 @@ class EmojiPracticeButtonState extends State<EmojiPracticeButton> {
}
}

bool get _canDoActivity {
final canDo = widget.token.shouldDoActivity(
a: ActivityTypeEnum.emoji,
feature: null,
tag: null,
);
return canDo;
}
bool get _shouldDoActivity => widget.token.shouldDoActivity(
a: ActivityTypeEnum.emoji,
feature: null,
tag: null,
);

@override
Widget build(BuildContext context) {
final emoji = widget.token.getEmoji();
return SizedBox(
height: 40,
width: 40,
child: _canDoActivity || emoji != null
? IconButton(
onPressed: () {
widget.onPressed();
if (widget.emoji == null && emoji != null) {
widget.setEmoji(emoji);
}
},
icon: emoji == null
? const Icon(Icons.add_reaction_outlined)
: Text(emoji),
child: _shouldDoActivity || emoji != null
? Opacity(
opacity: _shouldDoActivity ? 0.5 : 1,
child: IconButton(
onPressed: () {
widget.onPressed();
if (widget.emoji == null && emoji != null) {
widget.setEmoji(emoji);
}
},
icon: emoji == null
? const Icon(Icons.add_reaction_outlined)
: Text(emoji),
),
)
: const SizedBox.shrink(),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ class WordAudioButtonState extends State<WordTextWithAudioButton> {
color: _isPlaying
? Theme.of(context).colorScheme.secondary
: null,
fontSize:
Theme.of(context).textTheme.titleLarge?.fontSize,
),
),
const SizedBox(width: 4),
Icon(
_isPlaying ? Icons.play_arrow : Icons.play_arrow_outlined,
size: Theme.of(context).textTheme.bodyMedium?.fontSize,
size: Theme.of(context).textTheme.titleLarge?.fontSize,
),
],
),
Expand Down
Loading

0 comments on commit f626d5f

Please sign in to comment.