moved functions for constructing constructs out of pangea message event so they can be created without direct access to the representation event
This commit is contained in:
parent
bead112d0d
commit
e7d176d182
6 changed files with 334 additions and 220 deletions
|
|
@ -2,20 +2,15 @@ import 'dart:convert';
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fluffychat/pangea/constants/choreo_constants.dart';
|
||||
import 'package:fluffychat/pangea/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart';
|
||||
import 'package:fluffychat/pangea/enum/audio_encoding_enum.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_representation_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
|
||||
import 'package:fluffychat/pangea/models/analytics/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/models/lemma.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/models/space_model.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
|
|
@ -673,158 +668,25 @@ class PangeaMessageEvent {
|
|||
List<OneConstructUse> get allConstructUses =>
|
||||
[..._grammarConstructUses, ..._vocabUses, ..._itStepsToConstructUses];
|
||||
|
||||
/// Returns a list of [OneConstructUse] from itSteps for which the continuance
|
||||
/// was selected or ignored. Correct selections are considered in the tokens
|
||||
/// flow. Once all continuances have lemmas, we can do both correct and incorrect
|
||||
/// in this flow. It actually doesn't do anything at all right now, because the
|
||||
/// choregrapher is not returning lemmas for continuances. This is a TODO.
|
||||
/// So currently only the lemmas can be gotten from the tokens for choices that
|
||||
/// are actually in the final message.
|
||||
List<OneConstructUse> get _itStepsToConstructUses {
|
||||
final List<OneConstructUse> uses = [];
|
||||
if (originalSent?.choreo == null) return uses;
|
||||
|
||||
for (final itStep in originalSent!.choreo!.itSteps) {
|
||||
for (final continuance in itStep.continuances) {
|
||||
final List<PangeaToken> tokensToSave =
|
||||
continuance.tokens.where((t) => t.lemma.saveVocab).toList();
|
||||
|
||||
if (originalSent!.choreo!.finalMessage.contains(continuance.text)) {
|
||||
continue;
|
||||
}
|
||||
if (continuance.wasClicked) {
|
||||
//PTODO - account for end of flow score
|
||||
if (continuance.level != ChoreoConstants.levelThresholdForGreen) {
|
||||
for (final token in tokensToSave) {
|
||||
uses.add(
|
||||
_lemmaToVocabUse(
|
||||
token.lemma,
|
||||
ConstructUseTypeEnum.incIt,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (continuance.level != ChoreoConstants.levelThresholdForGreen) {
|
||||
for (final token in tokensToSave) {
|
||||
uses.add(
|
||||
_lemmaToVocabUse(
|
||||
token.lemma,
|
||||
ConstructUseTypeEnum.ignIt,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uses;
|
||||
}
|
||||
/// Returns a list of [OneConstructUse] from itSteps
|
||||
List<OneConstructUse> get _itStepsToConstructUses =>
|
||||
originalSent?.choreo?.itStepsToConstructUses(event: event) ?? [];
|
||||
|
||||
/// get construct uses of type vocab for the message
|
||||
List<OneConstructUse> get _vocabUses {
|
||||
final List<OneConstructUse> uses = [];
|
||||
|
||||
// missing vital info so return
|
||||
if (event.roomId == null || originalSent?.tokens == null) {
|
||||
// debugger(when: kDebugMode);
|
||||
return uses;
|
||||
}
|
||||
|
||||
// for each token, record whether selected in ga, ta, or wa
|
||||
for (final token in originalSent!.tokens!
|
||||
.where((token) => token.lemma.saveVocab)
|
||||
.toList()) {
|
||||
uses.add(_getVocabUseForToken(token));
|
||||
}
|
||||
|
||||
return uses;
|
||||
}
|
||||
|
||||
/// Returns a [OneConstructUse] for the given [token]
|
||||
/// If there is no [originalSent] or [originalSent.choreo], the [token] is
|
||||
/// considered to be a [ConstructUseTypeEnum.wa] as long as it matches the target language.
|
||||
/// Later on, we may want to consider putting it in some category of like 'pending'
|
||||
/// If the [token] is in the [originalSent.choreo.acceptedOrIgnoredMatch],
|
||||
/// it is considered to be a [ConstructUseTypeEnum.ga].
|
||||
/// If the [token] is in the [originalSent.choreo.acceptedOrIgnoredMatch.choices],
|
||||
/// it is considered to be a [ConstructUseTypeEnum.corIt].
|
||||
/// If the [token] is not included in any choreoStep, it is considered to be a [ConstructUseTypeEnum.wa].
|
||||
OneConstructUse _getVocabUseForToken(PangeaToken token) {
|
||||
if (originalSent?.choreo == null) {
|
||||
final bool inUserL2 = originalSent?.langCode == l2Code;
|
||||
return _lemmaToVocabUse(
|
||||
token.lemma,
|
||||
inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk,
|
||||
if (originalSent?.tokens != null) {
|
||||
return originalSent!.content.vocabUses(
|
||||
event: event,
|
||||
choreo: originalSent!.choreo,
|
||||
tokens: originalSent!.tokens!,
|
||||
);
|
||||
}
|
||||
|
||||
for (final step in originalSent!.choreo!.choreoSteps) {
|
||||
/// if 1) accepted match 2) token is in the replacement and 3) replacement
|
||||
/// is in the overall step text, then token was a ga
|
||||
if (step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted &&
|
||||
(step.acceptedOrIgnoredMatch!.match.choices?.any(
|
||||
(r) =>
|
||||
r.value.contains(token.text.content) &&
|
||||
step.text.contains(r.value),
|
||||
) ??
|
||||
false)) {
|
||||
return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.ga);
|
||||
}
|
||||
if (step.itStep != null) {
|
||||
final bool pickedThroughIT =
|
||||
step.itStep!.chosenContinuance?.text.contains(token.text.content) ??
|
||||
false;
|
||||
if (pickedThroughIT) {
|
||||
return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.corIt);
|
||||
//PTODO - check if added via custom input in IT flow
|
||||
}
|
||||
}
|
||||
}
|
||||
return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.wa);
|
||||
return [];
|
||||
}
|
||||
|
||||
OneConstructUse _lemmaToVocabUse(
|
||||
Lemma lemma,
|
||||
ConstructUseTypeEnum type,
|
||||
) =>
|
||||
OneConstructUse(
|
||||
useType: type,
|
||||
chatId: event.roomId!,
|
||||
timeStamp: event.originServerTs,
|
||||
lemma: lemma.text,
|
||||
form: lemma.form,
|
||||
msgId: event.eventId,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
);
|
||||
|
||||
/// get construct uses of type grammar for the message
|
||||
List<OneConstructUse> get _grammarConstructUses {
|
||||
final List<OneConstructUse> uses = [];
|
||||
|
||||
if (originalSent?.choreo == null || event.roomId == null) return uses;
|
||||
|
||||
for (final step in originalSent!.choreo!.choreoSteps) {
|
||||
if (step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted) {
|
||||
final String name = step.acceptedOrIgnoredMatch!.match.rule?.id ??
|
||||
step.acceptedOrIgnoredMatch!.match.shortMessage ??
|
||||
step.acceptedOrIgnoredMatch!.match.type.typeName.name;
|
||||
uses.add(
|
||||
OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.ga,
|
||||
chatId: event.roomId!,
|
||||
timeStamp: event.originServerTs,
|
||||
lemma: name,
|
||||
form: name,
|
||||
msgId: event.eventId,
|
||||
constructType: ConstructTypeEnum.grammar,
|
||||
id: "${event.eventId}_${step.acceptedOrIgnoredMatch!.match.offset}_${step.acceptedOrIgnoredMatch!.match.length}",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
return uses;
|
||||
}
|
||||
List<OneConstructUse> get _grammarConstructUses =>
|
||||
originalSent?.choreo?.grammarConstructUses(event: event) ?? [];
|
||||
}
|
||||
|
||||
class URLFinder {
|
||||
|
|
|
|||
|
|
@ -72,9 +72,11 @@ class PracticeActivityRecordEvent {
|
|||
//TODO - find form of construct within the message
|
||||
//this is related to the feature of highlighting the target construct in the message
|
||||
form: construct.lemma,
|
||||
chatId: event.roomId ?? practiceEvent.roomId ?? timeline.room.id,
|
||||
msgId: practiceActivity.parentMessageId,
|
||||
timeStamp: event.originServerTs,
|
||||
metadata: ConstructUseMetaData(
|
||||
roomId: event.roomId ?? practiceEvent.roomId ?? timeline.room.id,
|
||||
eventId: practiceActivity.parentMessageId,
|
||||
timeStamp: event.originServerTs,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,12 +37,14 @@ class ConstructAnalyticsModel {
|
|||
for (final useData in lemmaUses) {
|
||||
final use = OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.ga,
|
||||
chatId: useData["chatId"],
|
||||
timeStamp: DateTime.parse(useData["timeStamp"]),
|
||||
lemma: lemma,
|
||||
form: useData["form"],
|
||||
msgId: useData["msgId"],
|
||||
constructType: ConstructTypeEnum.grammar,
|
||||
metadata: ConstructUseMetaData(
|
||||
eventId: useData["msgId"],
|
||||
roomId: useData["chatId"],
|
||||
timeStamp: DateTime.parse(useData["timeStamp"]),
|
||||
),
|
||||
);
|
||||
uses.add(use);
|
||||
}
|
||||
|
|
@ -69,71 +71,6 @@ class ConstructAnalyticsModel {
|
|||
}
|
||||
}
|
||||
|
||||
class OneConstructUse {
|
||||
String? lemma;
|
||||
ConstructTypeEnum? constructType;
|
||||
String? form;
|
||||
ConstructUseTypeEnum useType;
|
||||
String chatId;
|
||||
String? msgId;
|
||||
DateTime timeStamp;
|
||||
String? id;
|
||||
|
||||
OneConstructUse({
|
||||
required this.useType,
|
||||
required this.chatId,
|
||||
required this.timeStamp,
|
||||
required this.lemma,
|
||||
required this.form,
|
||||
required this.msgId,
|
||||
required this.constructType,
|
||||
this.id,
|
||||
});
|
||||
|
||||
factory OneConstructUse.fromJson(Map<String, dynamic> json) {
|
||||
return OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.values
|
||||
.firstWhere((e) => e.string == json['useType']),
|
||||
chatId: json['chatId'],
|
||||
timeStamp: DateTime.parse(json['timeStamp']),
|
||||
lemma: json['lemma'],
|
||||
form: json['form'],
|
||||
msgId: json['msgId'],
|
||||
constructType: json['constructType'] != null
|
||||
? ConstructTypeUtil.fromString(json['constructType'])
|
||||
: null,
|
||||
id: json['id'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson([bool condensed = false]) {
|
||||
final Map<String, String?> data = {
|
||||
'useType': useType.string,
|
||||
'chatId': chatId,
|
||||
'timeStamp': timeStamp.toIso8601String(),
|
||||
'form': form,
|
||||
'msgId': msgId,
|
||||
};
|
||||
if (!condensed && lemma != null) data['lemma'] = lemma!;
|
||||
if (!condensed && constructType != null) {
|
||||
data['constructType'] = constructType!.string;
|
||||
}
|
||||
if (id != null) data['id'] = id;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Room? getRoom(Client client) {
|
||||
return client.getRoomById(chatId);
|
||||
}
|
||||
|
||||
Future<Event?> getEvent(Client client) async {
|
||||
final Room? room = getRoom(client);
|
||||
if (room == null || msgId == null) return null;
|
||||
return room.getEventById(msgId!);
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructUses {
|
||||
final List<OneConstructUse> uses;
|
||||
final ConstructTypeEnum constructType;
|
||||
|
|
@ -145,3 +82,82 @@ class ConstructUses {
|
|||
required this.lemma,
|
||||
});
|
||||
}
|
||||
|
||||
class OneConstructUse {
|
||||
String? lemma;
|
||||
ConstructTypeEnum? constructType;
|
||||
String? form;
|
||||
ConstructUseTypeEnum useType;
|
||||
String? id;
|
||||
ConstructUseMetaData metadata;
|
||||
|
||||
OneConstructUse({
|
||||
required this.useType,
|
||||
required this.lemma,
|
||||
required this.form,
|
||||
required this.constructType,
|
||||
required this.metadata,
|
||||
this.id,
|
||||
});
|
||||
|
||||
String get chatId => metadata.roomId;
|
||||
String get msgId => metadata.eventId!;
|
||||
DateTime get timeStamp => metadata.timeStamp;
|
||||
|
||||
factory OneConstructUse.fromJson(Map<String, dynamic> json) {
|
||||
return OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.values
|
||||
.firstWhere((e) => e.string == json['useType']),
|
||||
lemma: json['lemma'],
|
||||
form: json['form'],
|
||||
constructType: json['constructType'] != null
|
||||
? ConstructTypeUtil.fromString(json['constructType'])
|
||||
: null,
|
||||
id: json['id'],
|
||||
metadata: ConstructUseMetaData(
|
||||
eventId: json['msgId'],
|
||||
roomId: json['chatId'],
|
||||
timeStamp: DateTime.parse(json['timeStamp']),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson([bool condensed = false]) {
|
||||
final Map<String, String?> data = {
|
||||
'useType': useType.string,
|
||||
'chatId': metadata.roomId,
|
||||
'timeStamp': metadata.timeStamp.toIso8601String(),
|
||||
'form': form,
|
||||
'msgId': metadata.eventId,
|
||||
};
|
||||
if (!condensed && lemma != null) data['lemma'] = lemma!;
|
||||
if (!condensed && constructType != null) {
|
||||
data['constructType'] = constructType!.string;
|
||||
}
|
||||
if (id != null) data['id'] = id;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Room? getRoom(Client client) {
|
||||
return client.getRoomById(metadata.roomId);
|
||||
}
|
||||
|
||||
Future<Event?> getEvent(Client client) async {
|
||||
final Room? room = getRoom(client);
|
||||
if (room == null || metadata.eventId == null) return null;
|
||||
return room.getEventById(metadata.eventId!);
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructUseMetaData {
|
||||
String? eventId;
|
||||
String roomId;
|
||||
DateTime timeStamp;
|
||||
|
||||
ConstructUseMetaData({
|
||||
required this.roomId,
|
||||
required this.timeStamp,
|
||||
this.eventId,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:fluffychat/pangea/constants/choreo_constants.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/analytics/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'it_step.dart';
|
||||
|
||||
|
|
@ -111,6 +117,100 @@ class ChoreoRecord {
|
|||
|
||||
String get finalMessage =>
|
||||
choreoSteps.isNotEmpty ? choreoSteps.last.text : "";
|
||||
|
||||
/// get construct uses of type grammar for the message
|
||||
List<OneConstructUse> grammarConstructUses({
|
||||
Event? event,
|
||||
ConstructUseMetaData? metadata,
|
||||
}) {
|
||||
final List<OneConstructUse> uses = [];
|
||||
if (event?.roomId == null && metadata?.roomId == null) {
|
||||
return uses;
|
||||
}
|
||||
metadata ??= ConstructUseMetaData(
|
||||
roomId: event!.roomId!,
|
||||
eventId: event.eventId,
|
||||
timeStamp: event.originServerTs,
|
||||
);
|
||||
|
||||
for (final step in choreoSteps) {
|
||||
if (step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted) {
|
||||
final String name = step.acceptedOrIgnoredMatch!.match.rule?.id ??
|
||||
step.acceptedOrIgnoredMatch!.match.shortMessage ??
|
||||
step.acceptedOrIgnoredMatch!.match.type.typeName.name;
|
||||
uses.add(
|
||||
OneConstructUse(
|
||||
useType: ConstructUseTypeEnum.ga,
|
||||
lemma: name,
|
||||
form: name,
|
||||
constructType: ConstructTypeEnum.grammar,
|
||||
id: "${metadata.eventId}_${step.acceptedOrIgnoredMatch!.match.offset}_${step.acceptedOrIgnoredMatch!.match.length}",
|
||||
metadata: metadata,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
return uses;
|
||||
}
|
||||
|
||||
/// Returns a list of [OneConstructUse] from itSteps for which the continuance
|
||||
/// was selected or ignored. Correct selections are considered in the tokens
|
||||
/// flow. Once all continuances have lemmas, we can do both correct and incorrect
|
||||
/// in this flow. It actually doesn't do anything at all right now, because the
|
||||
/// choregrapher is not returning lemmas for continuances. This is a TODO.
|
||||
/// So currently only the lemmas can be gotten from the tokens for choices that
|
||||
/// are actually in the final message.
|
||||
List<OneConstructUse> itStepsToConstructUses({
|
||||
Event? event,
|
||||
ConstructUseMetaData? metadata,
|
||||
}) {
|
||||
final List<OneConstructUse> uses = [];
|
||||
if (event == null && metadata == null) {
|
||||
return uses;
|
||||
}
|
||||
|
||||
metadata ??= ConstructUseMetaData(
|
||||
roomId: event!.roomId!,
|
||||
eventId: event.eventId,
|
||||
timeStamp: event.originServerTs,
|
||||
);
|
||||
|
||||
for (final itStep in itSteps) {
|
||||
for (final continuance in itStep.continuances) {
|
||||
final List<PangeaToken> tokensToSave =
|
||||
continuance.tokens.where((t) => t.lemma.saveVocab).toList();
|
||||
|
||||
if (finalMessage.contains(continuance.text)) {
|
||||
continue;
|
||||
}
|
||||
if (continuance.wasClicked) {
|
||||
//PTODO - account for end of flow score
|
||||
if (continuance.level != ChoreoConstants.levelThresholdForGreen) {
|
||||
for (final token in tokensToSave) {
|
||||
uses.add(
|
||||
token.lemma.toVocabUse(
|
||||
ConstructUseTypeEnum.incIt,
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (continuance.level != ChoreoConstants.levelThresholdForGreen) {
|
||||
for (final token in tokensToSave) {
|
||||
uses.add(
|
||||
token.lemma.toVocabUse(
|
||||
ConstructUseTypeEnum.ignIt,
|
||||
metadata,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uses;
|
||||
}
|
||||
}
|
||||
|
||||
/// A new ChoreoRecordStep is saved in the following cases:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/analytics/constructs_model.dart';
|
||||
|
||||
/// Represents a lemma object
|
||||
class Lemma {
|
||||
/// [text] ex "ir" - text of the lemma of the word
|
||||
|
|
@ -35,4 +39,18 @@ class Lemma {
|
|||
|
||||
static Lemma create(String form) =>
|
||||
Lemma(text: '', saveVocab: true, form: form);
|
||||
|
||||
/// Given a [type] and [metadata], returns a [OneConstructUse] for this lemma
|
||||
OneConstructUse toVocabUse(
|
||||
ConstructUseTypeEnum type,
|
||||
ConstructUseMetaData metadata,
|
||||
) {
|
||||
return OneConstructUse(
|
||||
useType: type,
|
||||
lemma: text,
|
||||
form: form,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
metadata: metadata,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/analytics/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
/// this class is contained within a [RepresentationEvent]
|
||||
|
|
@ -81,4 +87,114 @@ class PangeaRepresentation {
|
|||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/// Get construct uses of type vocab for the message.
|
||||
/// Takes a list of tokens and a choreo record, which is searched
|
||||
/// through for each token for its construct use type.
|
||||
/// Also takes either an event (typically when the Representation itself is
|
||||
/// available) or construct use metadata (when the event is not available,
|
||||
/// i.e. immediately after message send) to create the construct use.
|
||||
List<OneConstructUse> vocabUses({
|
||||
required List<PangeaToken> tokens,
|
||||
Event? event,
|
||||
ConstructUseMetaData? metadata,
|
||||
ChoreoRecord? choreo,
|
||||
}) {
|
||||
final List<OneConstructUse> uses = [];
|
||||
|
||||
// missing vital info so return
|
||||
if (event?.roomId == null && metadata?.roomId == null) {
|
||||
// debugger(when: kDebugMode);
|
||||
return uses;
|
||||
}
|
||||
|
||||
metadata ??= ConstructUseMetaData(
|
||||
roomId: event!.roomId!,
|
||||
eventId: event.eventId,
|
||||
timeStamp: event.originServerTs,
|
||||
);
|
||||
|
||||
// for each token, record whether selected in ga, ta, or wa
|
||||
final tokensToSave =
|
||||
tokens.where((token) => token.lemma.saveVocab).toList();
|
||||
for (final token in tokensToSave) {
|
||||
uses.add(
|
||||
getVocabUseForToken(
|
||||
token,
|
||||
metadata,
|
||||
choreo: choreo,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return uses;
|
||||
}
|
||||
|
||||
/// Returns a [OneConstructUse] for the given [token]
|
||||
/// If there is no [choreo], the [token] is
|
||||
/// considered to be a [ConstructUseTypeEnum.wa] as long as it matches the target language.
|
||||
/// Later on, we may want to consider putting it in some category of like 'pending'
|
||||
/// If the [token] is in the [choreo.acceptedOrIgnoredMatch], it is considered to be a [ConstructUseTypeEnum.ga].
|
||||
/// If the [token] is in the [choreo.acceptedOrIgnoredMatch.choices], it is considered to be a [ConstructUseTypeEnum.corIt].
|
||||
/// If the [token] is not included in any choreoStep, it is considered to be a [ConstructUseTypeEnum.wa].
|
||||
OneConstructUse getVocabUseForToken(
|
||||
PangeaToken token,
|
||||
ConstructUseMetaData metadata, {
|
||||
ChoreoRecord? choreo,
|
||||
}) {
|
||||
final lemma = token.lemma;
|
||||
final content = token.text.content;
|
||||
|
||||
if (choreo == null) {
|
||||
final bool inUserL2 = langCode ==
|
||||
MatrixState.pangeaController.languageController.activeL2Code();
|
||||
return lemma.toVocabUse(
|
||||
inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk,
|
||||
metadata,
|
||||
);
|
||||
}
|
||||
|
||||
for (final step in choreo.choreoSteps) {
|
||||
/// if 1) accepted match 2) token is in the replacement and 3) replacement
|
||||
/// is in the overall step text, then token was a ga
|
||||
final bool isAcceptedMatch =
|
||||
step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted;
|
||||
final bool isITStep = step.itStep != null;
|
||||
if (!isAcceptedMatch && !isITStep) continue;
|
||||
|
||||
if (isAcceptedMatch &&
|
||||
step.acceptedOrIgnoredMatch?.match.choices != null) {
|
||||
final choices = step.acceptedOrIgnoredMatch!.match.choices!;
|
||||
final bool stepContainedToken = choices.any(
|
||||
(choice) =>
|
||||
// if this choice contains the token's content
|
||||
choice.value.contains(content) &&
|
||||
// if the complete input text after this step
|
||||
// contains the choice (why is this here?)
|
||||
step.text.contains(choice.value),
|
||||
);
|
||||
if (stepContainedToken) {
|
||||
return lemma.toVocabUse(
|
||||
ConstructUseTypeEnum.ga,
|
||||
metadata,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isITStep && step.itStep?.chosenContinuance != null) {
|
||||
final bool pickedThroughIT =
|
||||
step.itStep!.chosenContinuance!.text.contains(content);
|
||||
if (pickedThroughIT) {
|
||||
return lemma.toVocabUse(
|
||||
ConstructUseTypeEnum.corIt,
|
||||
metadata,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return lemma.toVocabUse(
|
||||
ConstructUseTypeEnum.wa,
|
||||
metadata,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue