reload derived analytics on server analyics update
This commit is contained in:
parent
62c91d9dcc
commit
811ba58c73
7 changed files with 63 additions and 54 deletions
|
|
@ -130,29 +130,24 @@ class AnalyticsDataService {
|
|||
await _analyticsClientGetter.database.updateUserID(client.userID!);
|
||||
}
|
||||
|
||||
final resp = await client.getUserProfile(client.userID!);
|
||||
final analyticsProfile = AnalyticsProfileModel.fromJson(
|
||||
resp.additionalProperties,
|
||||
);
|
||||
|
||||
_syncController?.dispose();
|
||||
_syncController = AnalyticsSyncController(
|
||||
client: client,
|
||||
dataService: this,
|
||||
);
|
||||
|
||||
await _syncController!.bulkUpdate();
|
||||
|
||||
final vocab = await getAggregatedConstructs(ConstructTypeEnum.vocab);
|
||||
final morphs = await getAggregatedConstructs(ConstructTypeEnum.morph);
|
||||
final constructs = [...vocab.values, ...morphs.values];
|
||||
final totalXP = constructs.fold(0, (total, c) => total + c.points);
|
||||
await _analyticsClientGetter.database.updateDerivedStats(
|
||||
DerivedAnalyticsDataModel(
|
||||
totalXP: totalXP,
|
||||
offset: analyticsProfile.xpOffset ?? 0,
|
||||
),
|
||||
final resp = await client.getUserProfile(client.userID!);
|
||||
final analyticsProfile = AnalyticsProfileModel.fromJson(
|
||||
resp.additionalProperties,
|
||||
);
|
||||
|
||||
final l2 = MatrixState.pangeaController.userController.userL2;
|
||||
if (l2 != null) {
|
||||
await updateXPOffset(analyticsProfile.xpOffsetByLanguage(l2) ?? 0);
|
||||
}
|
||||
|
||||
_syncController!.start();
|
||||
|
||||
await _initMergeTable();
|
||||
|
|
@ -161,7 +156,7 @@ class AnalyticsDataService {
|
|||
} finally {
|
||||
Logs().i("Analytics database initialized.");
|
||||
initCompleter.complete();
|
||||
updateDispatcher.sendConstructAnalyticsUpdate(AnalyticsUpdate([]));
|
||||
updateDispatcher.sendLocalAnalyticsUpdate(AnalyticsUpdate([]));
|
||||
updateDispatcher.sendActivityAnalyticsUpdate(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -422,7 +417,7 @@ class AnalyticsDataService {
|
|||
events.add(XPGainedEvent(points, update.targetID));
|
||||
}
|
||||
|
||||
final newData = prevData.copyWith(totalXP: prevData.totalXP + points);
|
||||
final newData = prevData.addXP(points);
|
||||
await _analyticsClientGetter.database.updateDerivedStats(newData);
|
||||
|
||||
// Update public profile each time that new analytics are added.
|
||||
|
|
@ -485,15 +480,25 @@ class AnalyticsDataService {
|
|||
return events;
|
||||
}
|
||||
|
||||
Future<void> updateServerAnalytics(
|
||||
Future<List<AnalyticsUpdateEvent>> updateServerAnalytics(
|
||||
List<ConstructAnalyticsEvent> events,
|
||||
) async {
|
||||
final List<AnalyticsUpdateEvent> updates = [];
|
||||
|
||||
_invalidateCaches();
|
||||
final blocked = blockedConstructs;
|
||||
for (final event in events) {
|
||||
_mergeTable.addConstructsByUses(event.content.uses, blocked);
|
||||
}
|
||||
await _analyticsClientGetter.database.updateServerAnalytics(events);
|
||||
final vocab = await getAggregatedConstructs(ConstructTypeEnum.vocab);
|
||||
final morphs = await getAggregatedConstructs(ConstructTypeEnum.morph);
|
||||
final constructs = [...vocab.values, ...morphs.values];
|
||||
final totalXP = constructs.fold(0, (total, c) => total + c.points);
|
||||
|
||||
await _analyticsClientGetter.database.updateTotalXP(totalXP);
|
||||
updates.add(XPGainedEvent(0, null));
|
||||
return updates;
|
||||
}
|
||||
|
||||
Future<void> updateBlockedConstructs(ConstructIdentifier constructId) async {
|
||||
|
|
@ -512,12 +517,10 @@ class AnalyticsDataService {
|
|||
level: newLevel,
|
||||
);
|
||||
|
||||
await _analyticsClientGetter.database.updateDerivedStats(
|
||||
DerivedAnalyticsDataModel(totalXP: newXP),
|
||||
);
|
||||
await _analyticsClientGetter.database.updateTotalXP(newXP);
|
||||
|
||||
_invalidateCaches();
|
||||
updateDispatcher.sendConstructAnalyticsUpdate(
|
||||
updateDispatcher.sendLocalAnalyticsUpdate(
|
||||
AnalyticsUpdate([], blockedConstruct: constructId),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,7 +468,15 @@ class AnalyticsDatabase with DatabaseFileStorage {
|
|||
Future<void> updateXPOffset(int offset) {
|
||||
return _transaction(() async {
|
||||
final stats = await getDerivedStats();
|
||||
final updatedStats = stats.copyWith(offset: offset);
|
||||
final updatedStats = stats.copyWithOffset(offset);
|
||||
await _derivedStatsBox.put('derived_stats', updatedStats.toJson());
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> updateTotalXP(int totalXP) {
|
||||
return _transaction(() async {
|
||||
final stats = await getDerivedStats();
|
||||
final updatedStats = stats.copyWithTotalXP(totalXP);
|
||||
await _derivedStatsBox.put('derived_stats', updatedStats.toJson());
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import 'dart:async';
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_data/analytics_data_service.dart';
|
||||
import 'package:fluffychat/pangea/analytics_data/analytics_update_dispatcher.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_event.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
|
|
@ -50,13 +49,8 @@ class AnalyticsSyncController {
|
|||
.toList();
|
||||
|
||||
if (constructEvents.isEmpty) return;
|
||||
await dataService.updateServerAnalytics(constructEvents);
|
||||
|
||||
// Server updates do not usually need to update the UI, since usually they are only
|
||||
// transfering local data to the server. However, if a user if using multiple devices,
|
||||
// we do need to update the UI when new data comes from the server.
|
||||
dataService.updateDispatcher.sendConstructAnalyticsUpdate(
|
||||
AnalyticsUpdate([]),
|
||||
await dataService.updateDispatcher.sendServerAnalyticsUpdate(
|
||||
constructEvents,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:fluffychat/pangea/analytics_data/analytics_data_service.dart';
|
||||
import 'package:fluffychat/pangea/analytics_data/analytics_update_events.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_event.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
|
||||
|
|
@ -85,9 +86,16 @@ class AnalyticsUpdateDispatcher {
|
|||
UserSetLemmaInfo lemmaInfo,
|
||||
) => _lemmaInfoUpdateStream.add(MapEntry(constructId, lemmaInfo));
|
||||
|
||||
Future<void> sendConstructAnalyticsUpdate(
|
||||
AnalyticsUpdate analyticsUpdate,
|
||||
Future<void> sendServerAnalyticsUpdate(
|
||||
List<ConstructAnalyticsEvent> events,
|
||||
) async {
|
||||
final updates = await dataService.updateServerAnalytics(events);
|
||||
for (final event in updates) {
|
||||
_dispatch(event);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sendLocalAnalyticsUpdate(AnalyticsUpdate analyticsUpdate) async {
|
||||
final events = await dataService.updateLocalAnalytics(analyticsUpdate);
|
||||
for (final event in events) {
|
||||
_dispatch(event);
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class AnalyticsUpdateService {
|
|||
List<OneConstructUse> newConstructs, {
|
||||
bool forceUpdate = false,
|
||||
}) async {
|
||||
await dataService.updateDispatcher.sendConstructAnalyticsUpdate(
|
||||
await dataService.updateDispatcher.sendLocalAnalyticsUpdate(
|
||||
AnalyticsUpdate(newConstructs, targetID: targetID),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
||||
class DerivedAnalyticsDataModel {
|
||||
|
|
@ -12,7 +11,7 @@ class DerivedAnalyticsDataModel {
|
|||
|
||||
int get totalXP => _totalXP + offset;
|
||||
|
||||
int get level => calculateLevelWithXp(_totalXP);
|
||||
int get level => calculateLevelWithXp(totalXP);
|
||||
|
||||
// the minimum XP required for a given level
|
||||
int get _minXPForLevel => calculateXpWithLevel(level);
|
||||
|
|
@ -23,7 +22,7 @@ class DerivedAnalyticsDataModel {
|
|||
// the progress within the current level as a percentage (0.0 to 1.0)
|
||||
double get levelProgress {
|
||||
final progress =
|
||||
(_totalXP - _minXPForLevel) / (minXPForNextLevel - _minXPForLevel);
|
||||
(totalXP - _minXPForLevel) / (minXPForNextLevel - _minXPForLevel);
|
||||
return progress >= 0 ? progress : 0;
|
||||
}
|
||||
|
||||
|
|
@ -60,35 +59,29 @@ class DerivedAnalyticsDataModel {
|
|||
}
|
||||
}
|
||||
|
||||
DerivedAnalyticsDataModel update(List<OneConstructUse> uses) {
|
||||
int xp = _totalXP;
|
||||
|
||||
for (final u in uses) {
|
||||
xp += u.xp;
|
||||
}
|
||||
|
||||
return copyWith(totalXP: xp);
|
||||
DerivedAnalyticsDataModel copyWithOffset(int offset) {
|
||||
return DerivedAnalyticsDataModel(totalXP: _totalXP, offset: offset);
|
||||
}
|
||||
|
||||
DerivedAnalyticsDataModel merge(DerivedAnalyticsDataModel other) {
|
||||
DerivedAnalyticsDataModel copyWithTotalXP(int totalXP) {
|
||||
return DerivedAnalyticsDataModel(totalXP: totalXP, offset: offset);
|
||||
}
|
||||
|
||||
DerivedAnalyticsDataModel addXP(int xpToAdd) {
|
||||
return DerivedAnalyticsDataModel(
|
||||
totalXP: _totalXP + other.totalXP,
|
||||
totalXP: _totalXP + xpToAdd,
|
||||
offset: offset,
|
||||
);
|
||||
}
|
||||
|
||||
DerivedAnalyticsDataModel copyWith({int? totalXP, int? offset}) {
|
||||
factory DerivedAnalyticsDataModel.fromJson(Map<String, dynamic> map) {
|
||||
return DerivedAnalyticsDataModel(
|
||||
totalXP: totalXP ?? this.totalXP,
|
||||
offset: offset ?? this.offset,
|
||||
totalXP: map['total_xp'] ?? 0,
|
||||
offset: map['offset'] ?? 0,
|
||||
);
|
||||
}
|
||||
|
||||
factory DerivedAnalyticsDataModel.fromJson(Map<String, dynamic> map) {
|
||||
return DerivedAnalyticsDataModel(totalXP: map['total_xp'] ?? 0);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {'total_xp': _totalXP};
|
||||
return {'total_xp': _totalXP, 'offset': offset};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@ class AnalyticsProfileModel {
|
|||
int? get level => languageAnalytics?[targetLanguage]?.level;
|
||||
|
||||
int? get xpOffset => languageAnalytics?[targetLanguage]?.xpOffset;
|
||||
|
||||
int? xpOffsetByLanguage(LanguageModel language) =>
|
||||
languageAnalytics?[language]?.xpOffset;
|
||||
}
|
||||
|
||||
class LanguageAnalyticsProfileEntry {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue