From f9ad45d20359c7a8972e4a6c29ded6b8e0db1b93 Mon Sep 17 00:00:00 2001 From: William Jordan-Cooley Date: Wed, 2 Oct 2024 17:40:16 -0400 Subject: [PATCH] intelligently choosing tokens and passing all their info --- lib/main.dart | 2 +- ...actice_activity_generation_controller.dart | 7 +- .../analytics/construct_list_model.dart | 4 +- .../message_activity_request.dart | 3 +- .../practice_activity_model.dart | 15 ++ .../multiple_choice_activity.dart | 50 +++--- .../practice_activity_card.dart | 152 +++++++++--------- 7 files changed, 128 insertions(+), 105 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 36add47dc..6be6edc91 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,7 +22,7 @@ void main() async { // #Pangea try { - await dotenv.load(fileName: ".env.local_choreo"); + await dotenv.load(fileName: ".env"); } catch (e) { Logs().e('Failed to load .env file', e); } diff --git a/lib/pangea/controllers/practice_activity_generation_controller.dart b/lib/pangea/controllers/practice_activity_generation_controller.dart index bdba9a611..bbe961ff8 100644 --- a/lib/pangea/controllers/practice_activity_generation_controller.dart +++ b/lib/pangea/controllers/practice_activity_generation_controller.dart @@ -121,11 +121,12 @@ class PracticeGenerationController { // if the server points to an existing event, return that event if (res.existingActivityEventId != null) { - debugPrint( - 'Existing activity event found: ${res.existingActivityEventId}', - ); final Event? existingEvent = await event.room.getEventById(res.existingActivityEventId!); + + debugPrint( + 'Existing activity event found: ${existingEvent?.content}', + ); if (existingEvent != null) { return PracticeActivityEvent( event: existingEvent, diff --git a/lib/pangea/models/analytics/construct_list_model.dart b/lib/pangea/models/analytics/construct_list_model.dart index 723f89423..d73b5060a 100644 --- a/lib/pangea/models/analytics/construct_list_model.dart +++ b/lib/pangea/models/analytics/construct_list_model.dart @@ -21,7 +21,7 @@ class ConstructListModel { }) : _uses = uses; List get uses => - _uses.where((use) => use.constructType == type).toList(); + _uses.where((use) => use.constructType == type || type == null).toList(); /// All unique lemmas used in the construct events List get lemmas => constructList.map((e) => e.lemma).toSet().toList(); @@ -38,7 +38,7 @@ class ConstructListModel { _constructMap = lemmaToUses.map( (key, value) => MapEntry( - key + value.first.constructType.string, + key, ConstructUses( uses: value, constructType: value.first.constructType, diff --git a/lib/pangea/models/practice_activities.dart/message_activity_request.dart b/lib/pangea/models/practice_activities.dart/message_activity_request.dart index 059f14d20..9dabc879d 100644 --- a/lib/pangea/models/practice_activities.dart/message_activity_request.dart +++ b/lib/pangea/models/practice_activities.dart/message_activity_request.dart @@ -27,11 +27,12 @@ class ConstructWithXP { } Map toJson() { - return { + final json = { 'construct_id': id.toJson(), 'xp': xp, 'last_used': lastUsed?.toIso8601String(), }; + return json; } } 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 0511d8055..4e93cb279 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_model.dart @@ -253,6 +253,21 @@ class PracticeActivityModel { this.freeResponse, }); + String get question { + switch (activityType) { + case ActivityTypeEnum.multipleChoice: + return multipleChoice!.question; + case ActivityTypeEnum.listening: + return listening!.text; + case ActivityTypeEnum.speaking: + return speaking!.text; + case ActivityTypeEnum.freeResponse: + return freeResponse!.question; + default: + return ''; + } + } + factory PracticeActivityModel.fromJson(Map json) { return PracticeActivityModel( tgtConstructs: (json['tgt_constructs'] as List) diff --git a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart index 0c426b8ac..16ddb164a 100644 --- a/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart +++ b/lib/pangea/widgets/practice_activity/multiple_choice_activity.dart @@ -1,6 +1,5 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart'; -import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; @@ -28,21 +27,22 @@ class MultipleChoiceActivityState extends State { PracticeActivityRecordModel? get currentRecordModel => widget.practiceCardController.currentCompletionRecord; - bool get isSubmitted => - widget.currentActivity?.latestUserRecord?.record.latestResponse != null; + // bool get isSubmitted => + // widget.currentActivity?.latestUserRecord?.record.latestResponse != null; @override void initState() { super.initState(); - setCompletionRecord(); + // setCompletionRecord(); } @override void didUpdateWidget(covariant MultipleChoiceActivity oldWidget) { super.didUpdateWidget(oldWidget); - if (oldWidget.currentActivity?.event.eventId != - widget.currentActivity?.event.eventId) { - setCompletionRecord(); + if (widget.practiceCardController.currentCompletionRecord?.responses + .isEmpty ?? + false) { + selectedChoiceIndex = null; } } @@ -52,21 +52,21 @@ class MultipleChoiceActivityState extends State { /// Otherwise, it sets the current model to the user record's record and /// determines the selected choice index. void setCompletionRecord() { - if (widget.currentActivity?.latestUserRecord?.record == null) { - widget.practiceCardController.setCompletionRecord( - PracticeActivityRecordModel( - question: - widget.currentActivity?.practiceActivity.multipleChoice!.question, - ), - ); - selectedChoiceIndex = null; - } else { - widget.practiceCardController.setCompletionRecord( - widget.currentActivity!.latestUserRecord!.record); - selectedChoiceIndex = widget - .currentActivity?.practiceActivity.multipleChoice! - .choiceIndex(currentRecordModel!.latestResponse!.text!); - } + // if (widget.currentActivity?.latestUserRecord?.record == null) { + widget.practiceCardController.setCompletionRecord( + PracticeActivityRecordModel( + question: + widget.currentActivity?.practiceActivity.multipleChoice!.question, + ), + ); + selectedChoiceIndex = null; + // } else { + // widget.practiceCardController.setCompletionRecord( + // widget.currentActivity!.latestUserRecord!.record); + // selectedChoiceIndex = widget + // .currentActivity?.practiceActivity.multipleChoice! + // .choiceIndex(currentRecordModel!.latestResponse!.text!); + // } setState(() {}); } @@ -79,8 +79,8 @@ class MultipleChoiceActivityState extends State { .currentActivity!.practiceActivity.multipleChoice! .isCorrect(value, index); - final ConstructUseTypeEnum useType = - isCorrect ? ConstructUseTypeEnum.corPA : ConstructUseTypeEnum.incPA; + // final ConstructUseTypeEnum useType = + // isCorrect ? ConstructUseTypeEnum.corPA : ConstructUseTypeEnum.incPA; currentRecordModel?.addResponse( text: value, @@ -146,7 +146,7 @@ class MultipleChoiceActivityState extends State { ), ) .toList(), - isActive: !isSubmitted, + isActive: true, ), ], ), diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index 7574290c1..253b21f47 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -73,17 +73,27 @@ class MessagePracticeActivityCardState extends State { setState(() => fetchingActivity = value); } - /// Set target tokens. + void _setPracticeActivity(PracticeActivityEvent? activity) { + if (activity == null) { + widget.overlayController.exitPracticeFlow(); + return; + } + + currentActivity = activity; + + currentCompletionRecord = PracticeActivityRecordModel( + question: activity.practiceActivity.question, + ); + + widget.overlayController.setSelectedSpan(currentActivity!.practiceActivity); + } + /// Get an existing activity if there is one. /// If not, get a new activity from the server. Future initialize() async { - currentActivity = - _fetchExistingIncompleteActivity() ?? await _fetchNewActivity(); - - currentActivity == null - ? widget.overlayController.exitPracticeFlow() - : widget.overlayController - .setSelectedSpan(currentActivity!.practiceActivity); + _setPracticeActivity( + _fetchExistingIncompleteActivity() ?? await _fetchNewActivity(), + ); } // if the user did the activity before but awhile ago and we don't have any @@ -178,77 +188,73 @@ class MessagePracticeActivityCardState extends State { /// Fetches a new activity if there are any left to complete. /// Exits the practice flow if there are no more activities. void onActivityFinish() async { - try { - if (currentCompletionRecord == null || currentActivity == null) { - debugger(when: kDebugMode); - return; - } - - // start joy timer - _savorTheJoy(); - - final uses = currentCompletionRecord!.uses( - currentActivity!.practiceActivity, - ConstructUseMetaData( - roomId: widget.pangeaMessageEvent.room.id, - timeStamp: DateTime.now(), - ), - ); + // try { + if (currentCompletionRecord == null || currentActivity == null) { + debugger(when: kDebugMode); + return; + } - // update the target tokens with the new construct uses - targetTokensController.updateTokensWithConstructs( - uses, - context, - widget.pangeaMessageEvent, - ); + // start joy timer + _savorTheJoy(); - MatrixState.pangeaController.myAnalytics.setState( - AnalyticsStream( - // note - this maybe should be the activity event id - eventId: widget.pangeaMessageEvent.eventId, - roomId: widget.pangeaMessageEvent.room.id, - constructs: uses, - ), - ); + final uses = currentCompletionRecord!.uses( + currentActivity!.practiceActivity, + ConstructUseMetaData( + roomId: widget.pangeaMessageEvent.room.id, + timeStamp: DateTime.now(), + ), + ); - // save the record without awaiting to avoid blocking the UI - // send a copy of the activity record to make sure its not overwritten by - // the new activity - MatrixState.pangeaController.activityRecordController - .send(currentCompletionRecord!, currentActivity!) - .catchError( - (e, s) => ErrorHandler.logError( - e: e, - s: s, - m: 'Failed to save record', - data: { - 'record': currentCompletionRecord?.toJson(), - 'activity': currentActivity?.practiceActivity.toJson(), - }, - ), - ); + // update the target tokens with the new construct uses + await targetTokensController.updateTokensWithConstructs( + uses, + context, + widget.pangeaMessageEvent, + ); - widget.overlayController.onActivityFinish(); + MatrixState.pangeaController.myAnalytics.setState( + AnalyticsStream( + // note - this maybe should be the activity event id + eventId: widget.pangeaMessageEvent.eventId, + roomId: widget.pangeaMessageEvent.room.id, + constructs: uses, + ), + ); - currentActivity = await _fetchNewActivity(); + // save the record without awaiting to avoid blocking the UI + // send a copy of the activity record to make sure its not overwritten by + // the new activity + MatrixState.pangeaController.activityRecordController + .send(currentCompletionRecord!, currentActivity!) + .catchError( + (e, s) => ErrorHandler.logError( + e: e, + s: s, + m: 'Failed to save record', + data: { + 'record': currentCompletionRecord?.toJson(), + 'activity': currentActivity?.practiceActivity.toJson(), + }, + ), + ); - currentActivity == null - ? widget.overlayController.exitPracticeFlow() - : widget.overlayController - .setSelectedSpan(currentActivity!.practiceActivity); - } catch (e, s) { - debugger(when: kDebugMode); - ErrorHandler.logError( - e: e, - s: s, - m: 'Failed to get new activity', - data: { - 'activity': currentActivity, - 'record': currentCompletionRecord, - }, - ); - widget.overlayController.exitPracticeFlow(); - } + widget.overlayController.onActivityFinish(); + + _setPracticeActivity(await _fetchNewActivity()); + + // } catch (e, s) { + // debugger(when: kDebugMode); + // ErrorHandler.logError( + // e: e, + // s: s, + // m: 'Failed to get new activity', + // data: { + // 'activity': currentActivity, + // 'record': currentCompletionRecord, + // }, + // ); + // widget.overlayController.exitPracticeFlow(); + // } } RepresentationEvent? get representation =>