intelligently choosing tokens and passing all their info

pull/1384/head
William Jordan-Cooley 1 year ago
parent 8bffe17455
commit f9ad45d203

@ -22,7 +22,7 @@ void main() async {
// #Pangea // #Pangea
try { try {
await dotenv.load(fileName: ".env.local_choreo"); await dotenv.load(fileName: ".env");
} catch (e) { } catch (e) {
Logs().e('Failed to load .env file', e); Logs().e('Failed to load .env file', e);
} }

@ -121,11 +121,12 @@ class PracticeGenerationController {
// if the server points to an existing event, return that event // if the server points to an existing event, return that event
if (res.existingActivityEventId != null) { if (res.existingActivityEventId != null) {
debugPrint(
'Existing activity event found: ${res.existingActivityEventId}',
);
final Event? existingEvent = final Event? existingEvent =
await event.room.getEventById(res.existingActivityEventId!); await event.room.getEventById(res.existingActivityEventId!);
debugPrint(
'Existing activity event found: ${existingEvent?.content}',
);
if (existingEvent != null) { if (existingEvent != null) {
return PracticeActivityEvent( return PracticeActivityEvent(
event: existingEvent, event: existingEvent,

@ -21,7 +21,7 @@ class ConstructListModel {
}) : _uses = uses; }) : _uses = uses;
List<OneConstructUse> get uses => List<OneConstructUse> 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 /// All unique lemmas used in the construct events
List<String> get lemmas => constructList.map((e) => e.lemma).toSet().toList(); List<String> get lemmas => constructList.map((e) => e.lemma).toSet().toList();
@ -38,7 +38,7 @@ class ConstructListModel {
_constructMap = lemmaToUses.map( _constructMap = lemmaToUses.map(
(key, value) => MapEntry( (key, value) => MapEntry(
key + value.first.constructType.string, key,
ConstructUses( ConstructUses(
uses: value, uses: value,
constructType: value.first.constructType, constructType: value.first.constructType,

@ -27,11 +27,12 @@ class ConstructWithXP {
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { final json = {
'construct_id': id.toJson(), 'construct_id': id.toJson(),
'xp': xp, 'xp': xp,
'last_used': lastUsed?.toIso8601String(), 'last_used': lastUsed?.toIso8601String(),
}; };
return json;
} }
} }

@ -253,6 +253,21 @@ class PracticeActivityModel {
this.freeResponse, 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<String, dynamic> json) { factory PracticeActivityModel.fromJson(Map<String, dynamic> json) {
return PracticeActivityModel( return PracticeActivityModel(
tgtConstructs: (json['tgt_constructs'] as List) tgtConstructs: (json['tgt_constructs'] as List)

@ -1,6 +1,5 @@
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:fluffychat/pangea/choreographer/widgets/choice_array.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/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_model.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
@ -28,21 +27,22 @@ class MultipleChoiceActivityState extends State<MultipleChoiceActivity> {
PracticeActivityRecordModel? get currentRecordModel => PracticeActivityRecordModel? get currentRecordModel =>
widget.practiceCardController.currentCompletionRecord; widget.practiceCardController.currentCompletionRecord;
bool get isSubmitted => // bool get isSubmitted =>
widget.currentActivity?.latestUserRecord?.record.latestResponse != null; // widget.currentActivity?.latestUserRecord?.record.latestResponse != null;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
setCompletionRecord(); // setCompletionRecord();
} }
@override @override
void didUpdateWidget(covariant MultipleChoiceActivity oldWidget) { void didUpdateWidget(covariant MultipleChoiceActivity oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (oldWidget.currentActivity?.event.eventId != if (widget.practiceCardController.currentCompletionRecord?.responses
widget.currentActivity?.event.eventId) { .isEmpty ??
setCompletionRecord(); false) {
selectedChoiceIndex = null;
} }
} }
@ -52,21 +52,21 @@ class MultipleChoiceActivityState extends State<MultipleChoiceActivity> {
/// Otherwise, it sets the current model to the user record's record and /// Otherwise, it sets the current model to the user record's record and
/// determines the selected choice index. /// determines the selected choice index.
void setCompletionRecord() { void setCompletionRecord() {
if (widget.currentActivity?.latestUserRecord?.record == null) { // if (widget.currentActivity?.latestUserRecord?.record == null) {
widget.practiceCardController.setCompletionRecord( widget.practiceCardController.setCompletionRecord(
PracticeActivityRecordModel( PracticeActivityRecordModel(
question: question:
widget.currentActivity?.practiceActivity.multipleChoice!.question, widget.currentActivity?.practiceActivity.multipleChoice!.question,
), ),
); );
selectedChoiceIndex = null; selectedChoiceIndex = null;
} else { // } else {
widget.practiceCardController.setCompletionRecord( // widget.practiceCardController.setCompletionRecord(
widget.currentActivity!.latestUserRecord!.record); // widget.currentActivity!.latestUserRecord!.record);
selectedChoiceIndex = widget // selectedChoiceIndex = widget
.currentActivity?.practiceActivity.multipleChoice! // .currentActivity?.practiceActivity.multipleChoice!
.choiceIndex(currentRecordModel!.latestResponse!.text!); // .choiceIndex(currentRecordModel!.latestResponse!.text!);
} // }
setState(() {}); setState(() {});
} }
@ -79,8 +79,8 @@ class MultipleChoiceActivityState extends State<MultipleChoiceActivity> {
.currentActivity!.practiceActivity.multipleChoice! .currentActivity!.practiceActivity.multipleChoice!
.isCorrect(value, index); .isCorrect(value, index);
final ConstructUseTypeEnum useType = // final ConstructUseTypeEnum useType =
isCorrect ? ConstructUseTypeEnum.corPA : ConstructUseTypeEnum.incPA; // isCorrect ? ConstructUseTypeEnum.corPA : ConstructUseTypeEnum.incPA;
currentRecordModel?.addResponse( currentRecordModel?.addResponse(
text: value, text: value,
@ -146,7 +146,7 @@ class MultipleChoiceActivityState extends State<MultipleChoiceActivity> {
), ),
) )
.toList(), .toList(),
isActive: !isSubmitted, isActive: true,
), ),
], ],
), ),

@ -73,17 +73,27 @@ class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
setState(() => fetchingActivity = value); 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. /// Get an existing activity if there is one.
/// If not, get a new activity from the server. /// If not, get a new activity from the server.
Future<void> initialize() async { Future<void> initialize() async {
currentActivity = _setPracticeActivity(
_fetchExistingIncompleteActivity() ?? await _fetchNewActivity(); _fetchExistingIncompleteActivity() ?? await _fetchNewActivity(),
);
currentActivity == null
? widget.overlayController.exitPracticeFlow()
: widget.overlayController
.setSelectedSpan(currentActivity!.practiceActivity);
} }
// if the user did the activity before but awhile ago and we don't have any // if the user did the activity before but awhile ago and we don't have any
@ -178,77 +188,73 @@ class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
/// Fetches a new activity if there are any left to complete. /// Fetches a new activity if there are any left to complete.
/// Exits the practice flow if there are no more activities. /// Exits the practice flow if there are no more activities.
void onActivityFinish() async { void onActivityFinish() async {
try { // try {
if (currentCompletionRecord == null || currentActivity == null) { if (currentCompletionRecord == null || currentActivity == null) {
debugger(when: kDebugMode); debugger(when: kDebugMode);
return; return;
} }
// start joy timer
_savorTheJoy();
final uses = currentCompletionRecord!.uses(
currentActivity!.practiceActivity,
ConstructUseMetaData(
roomId: widget.pangeaMessageEvent.room.id,
timeStamp: DateTime.now(),
),
);
// update the target tokens with the new construct uses // start joy timer
targetTokensController.updateTokensWithConstructs( _savorTheJoy();
uses,
context,
widget.pangeaMessageEvent,
);
MatrixState.pangeaController.myAnalytics.setState( final uses = currentCompletionRecord!.uses(
AnalyticsStream( currentActivity!.practiceActivity,
// note - this maybe should be the activity event id ConstructUseMetaData(
eventId: widget.pangeaMessageEvent.eventId, roomId: widget.pangeaMessageEvent.room.id,
roomId: widget.pangeaMessageEvent.room.id, timeStamp: DateTime.now(),
constructs: uses, ),
), );
);
// save the record without awaiting to avoid blocking the UI // update the target tokens with the new construct uses
// send a copy of the activity record to make sure its not overwritten by await targetTokensController.updateTokensWithConstructs(
// the new activity uses,
MatrixState.pangeaController.activityRecordController context,
.send(currentCompletionRecord!, currentActivity!) widget.pangeaMessageEvent,
.catchError( );
(e, s) => ErrorHandler.logError(
e: e,
s: s,
m: 'Failed to save record',
data: {
'record': currentCompletionRecord?.toJson(),
'activity': currentActivity?.practiceActivity.toJson(),
},
),
);
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.onActivityFinish();
? widget.overlayController.exitPracticeFlow()
: widget.overlayController _setPracticeActivity(await _fetchNewActivity());
.setSelectedSpan(currentActivity!.practiceActivity);
} catch (e, s) { // } catch (e, s) {
debugger(when: kDebugMode); // debugger(when: kDebugMode);
ErrorHandler.logError( // ErrorHandler.logError(
e: e, // e: e,
s: s, // s: s,
m: 'Failed to get new activity', // m: 'Failed to get new activity',
data: { // data: {
'activity': currentActivity, // 'activity': currentActivity,
'record': currentCompletionRecord, // 'record': currentCompletionRecord,
}, // },
); // );
widget.overlayController.exitPracticeFlow(); // widget.overlayController.exitPracticeFlow();
} // }
} }
RepresentationEvent? get representation => RepresentationEvent? get representation =>

Loading…
Cancel
Save