@@ -18,6 +18,8 @@ import 'package:fluffychat/pangea/common/constants/local.key.dart';
18
18
import 'package:fluffychat/pangea/common/controllers/base_controller.dart' ;
19
19
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart' ;
20
20
import 'package:fluffychat/pangea/common/utils/error_handler.dart' ;
21
+ import 'package:fluffychat/pangea/constructs/construct_repo.dart' ;
22
+ import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart' ;
21
23
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart' ;
22
24
import 'package:fluffychat/pangea/learning_settings/models/language_model.dart' ;
23
25
@@ -141,8 +143,12 @@ class GetAnalyticsController extends BaseController {
141
143
if (analyticsUpdate.type == AnalyticsUpdateType .server) {
142
144
await _getConstructs (forceUpdate: true );
143
145
}
144
- if (oldLevel < constructListModel.level) _onLevelUp ();
145
- if (oldLevel > constructListModel.level) await _onLevelDown (oldLevel);
146
+ if (oldLevel < constructListModel.level) {
147
+ await _onLevelUp (oldLevel, constructListModel.level);
148
+ }
149
+ if (oldLevel > constructListModel.level) {
150
+ await _onLevelDown (constructListModel.level, oldLevel);
151
+ }
146
152
_updateAnalyticsStream (origin: analyticsUpdate.origin);
147
153
// Update public profile each time that new analytics are added.
148
154
// If the level hasn't changed, this will not send an update to the server.
@@ -158,13 +164,22 @@ class GetAnalyticsController extends BaseController {
158
164
}) =>
159
165
analyticsStream.add (AnalyticsStreamUpdate (origin: origin));
160
166
161
- void _onLevelUp () {
162
- setState ({'level_up' : constructListModel.level});
167
+ Future <void > _onLevelUp (final int lowerLevel, final int upperLevel) async {
168
+ final result = await _generateLevelUpAnalyticsAndSaveToStateEvent (
169
+ lowerLevel,
170
+ upperLevel,
171
+ );
172
+ setState ({
173
+ 'level_up' : constructListModel.level,
174
+ 'analytics_room_id' : _client.analyticsRoomLocal (_l2! )? .id,
175
+ "construct_summary_state_event_id" : result? .stateEventId,
176
+ "construct_summary" : result? .summary,
177
+ });
163
178
}
164
179
165
- Future <void > _onLevelDown (final prevLevel ) async {
180
+ Future <void > _onLevelDown (final int lowerLevel, final int upperLevel ) async {
166
181
final offset =
167
- _calculateMinXpForLevel (prevLevel ) - constructListModel.totalXP;
182
+ _calculateMinXpForLevel (lowerLevel ) - constructListModel.totalXP;
168
183
await _pangeaController.userController.addXPOffset (offset);
169
184
constructListModel.updateConstructs (
170
185
[],
@@ -344,6 +359,90 @@ class GetAnalyticsController extends BaseController {
344
359
);
345
360
_cache.add (entry);
346
361
}
362
+
363
+ Future <GenerateConstructSummaryResult ?>
364
+ _generateLevelUpAnalyticsAndSaveToStateEvent (
365
+ final int lowerLevel,
366
+ final int upperLevel,
367
+ ) async {
368
+ // generate level up analytics as a construct summary
369
+ ConstructSummary summary;
370
+ try {
371
+ final int maxXP = _calculateMinXpForLevel (upperLevel);
372
+ final int minXP = _calculateMinXpForLevel (lowerLevel);
373
+ int diffXP = maxXP - minXP;
374
+ if (diffXP < 0 ) diffXP = 0 ;
375
+
376
+ // compute construct use of current level
377
+ final List <OneConstructUse > constructUseOfCurrentLevel = [];
378
+ int score = 0 ;
379
+ for (final use in constructListModel.uses) {
380
+ constructUseOfCurrentLevel.add (use);
381
+ score += use.pointValue;
382
+ if (score >= diffXP) break ;
383
+ }
384
+
385
+ // extract construct use message bodies for analytics
386
+ List <String ?>? constructUseMessageContentBodies = [];
387
+ for (final use in constructUseOfCurrentLevel) {
388
+ try {
389
+ final useMessage = await use.getEvent (_client);
390
+ final useMessageBody = useMessage? .content["body" ];
391
+ if (useMessageBody is String ) {
392
+ constructUseMessageContentBodies.add (useMessageBody);
393
+ } else {
394
+ constructUseMessageContentBodies.add (null );
395
+ }
396
+ } catch (e) {
397
+ constructUseMessageContentBodies.add (null );
398
+ }
399
+ }
400
+ if (constructUseMessageContentBodies.length !=
401
+ constructUseOfCurrentLevel.length) {
402
+ constructUseMessageContentBodies = null ;
403
+ }
404
+
405
+ final request = ConstructSummaryRequest (
406
+ constructs: constructUseOfCurrentLevel,
407
+ constructUseMessageContentBodies: constructUseMessageContentBodies,
408
+ language: _l2! .langCodeShort,
409
+ upperLevel: upperLevel,
410
+ lowerLevel: lowerLevel,
411
+ );
412
+
413
+ final response = await ConstructRepo .generateConstructSummary (request);
414
+ summary = response.summary;
415
+ } catch (e) {
416
+ debugPrint ("Error generating level up analytics: $e " );
417
+ ErrorHandler .logError (e: e, data: {'e' : e});
418
+ return null ;
419
+ }
420
+ String stateEventId;
421
+ try {
422
+ final Room ? analyticsRoom = _client.analyticsRoomLocal (_l2! );
423
+ if (analyticsRoom == null ) {
424
+ ErrorHandler .logError (
425
+ e: e,
426
+ data: {'e' : e, 'message' : "Analytics room not found for user" },
427
+ );
428
+ return null ;
429
+ }
430
+ stateEventId = await _client.setRoomStateWithKey (
431
+ analyticsRoom.id,
432
+ PangeaEventTypes .constructSummary,
433
+ '' ,
434
+ summary.toJson (),
435
+ );
436
+ } catch (e) {
437
+ debugPrint ("Error saving construct summary room: $e " );
438
+ ErrorHandler .logError (e: e, data: {'e' : e});
439
+ return null ;
440
+ }
441
+ return GenerateConstructSummaryResult (
442
+ stateEventId: stateEventId,
443
+ summary: summary,
444
+ );
445
+ }
347
446
}
348
447
349
448
class AnalyticsCacheEntry {
0 commit comments