fluffychat/lib/pangea/models/practice_activities.dart/message_activity_request.dart
ggurdin 1317989db0
1179 toolbar changes (#1209)
* updated toolbar buttons

* initial work for toolbar updates

* Add WordZoomWidget to display word and lemma information (#1214)

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/pangeachat/client/tree/1179-toolbar-changes?shareId=XXXX-XXXX-XXXX-XXXX).

* word zoom card prototyped, activity generation in progress

* adding copy for new construct uses

* laying down TODOs

* initial work for word zoom card

* Always add part of speech to token's morph list

* Prevent duplicate choices in lemma activity

* Don't play token audio at start of morph activity

* Only grant +1 points for emoji activity

* Uncomment tryToSpeak function

* Always update activity once complete

* Added queuing / UI logic for morph activity buttons

* code cleanup

* added required data argument to logError calls

* fix overflowing practice activity card and audio player on mobile

---------

Co-authored-by: wcjord <32568597+wcjord@users.noreply.github.com>
2024-12-27 12:42:49 -05:00

143 lines
4.1 KiB
Dart

import 'package:collection/collection.dart';
import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
// includes feedback text and the bad activity model
class ActivityQualityFeedback {
final String feedbackText;
final PracticeActivityModel badActivity;
ActivityQualityFeedback({
required this.feedbackText,
required this.badActivity,
});
factory ActivityQualityFeedback.fromJson(Map<String, dynamic> json) {
return ActivityQualityFeedback(
feedbackText: json['feedback_text'] as String,
badActivity: PracticeActivityModel.fromJson(
json['bad_activity'] as Map<String, dynamic>,
),
);
}
Map<String, dynamic> toJson() {
return {
'feedback_text': feedbackText,
'bad_activity': badActivity.toJson(),
};
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ActivityQualityFeedback &&
other.feedbackText == feedbackText &&
other.badActivity == badActivity;
}
@override
int get hashCode {
return feedbackText.hashCode ^ badActivity.hashCode;
}
}
class MessageActivityRequest {
final String userL1;
final String userL2;
final String messageText;
final List<PangeaToken> messageTokens;
final List<PangeaToken> targetTokens;
final ActivityTypeEnum targetType;
final String? targetMorphFeature;
final ActivityQualityFeedback? activityQualityFeedback;
MessageActivityRequest({
required this.userL1,
required this.userL2,
required this.messageText,
required this.messageTokens,
required this.activityQualityFeedback,
required this.targetTokens,
required this.targetType,
required this.targetMorphFeature,
}) {
if (targetTokens.isEmpty) {
throw Exception('Target tokens must not be empty');
}
if ([ActivityTypeEnum.wordFocusListening, ActivityTypeEnum.wordMeaning]
.contains(targetType) &&
targetTokens.length > 1) {
throw Exception(
'Target tokens must be a single token for this activity type',
);
}
}
Map<String, dynamic> toJson() {
return {
'user_l1': userL1,
'user_l2': userL2,
'message_text': messageText,
'message_tokens': messageTokens.map((e) => e.toJson()).toList(),
'activity_quality_feedback': activityQualityFeedback?.toJson(),
'target_tokens': targetTokens.map((e) => e.toJson()).toList(),
'target_type': targetType.string,
'target_morph_feature': targetMorphFeature,
};
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is MessageActivityRequest &&
other.messageText == messageText &&
other.targetType == targetType &&
other.activityQualityFeedback?.feedbackText ==
activityQualityFeedback?.feedbackText &&
const ListEquality().equals(other.targetTokens, targetTokens) &&
other.targetMorphFeature == targetMorphFeature;
}
@override
int get hashCode {
return messageText.hashCode ^
targetType.hashCode ^
activityQualityFeedback.hashCode ^
targetTokens.hashCode ^
targetMorphFeature.hashCode;
}
}
class MessageActivityResponse {
final PracticeActivityModel activity;
MessageActivityResponse({
required this.activity,
});
factory MessageActivityResponse.fromJson(Map<String, dynamic> json) {
if (!json.containsKey('activity')) {
Sentry.addBreadcrumb(Breadcrumb(data: {"json": json}));
throw Exception('Activity not found in message activity response');
}
if (json['activity'] is! Map<String, dynamic>) {
Sentry.addBreadcrumb(Breadcrumb(data: {"json": json}));
throw Exception('Activity is not a map in message activity response');
}
return MessageActivityResponse(
activity: PracticeActivityModel.fromJson(
json['activity'] as Map<String, dynamic>,
),
);
}
}