2025-12-13 13:27:05 +00:00
|
|
|
import 'package:drift/drift.dart';
|
|
|
|
|
import '../database.dart';
|
|
|
|
|
import '../tables/statistics.dart';
|
|
|
|
|
import '../tables/users.dart';
|
|
|
|
|
|
|
|
|
|
part 'statistics_dao.g.dart';
|
|
|
|
|
|
|
|
|
|
@DriftAccessor(tables: [StudySessions])
|
|
|
|
|
class StatisticsDao extends DatabaseAccessor<AppDatabase> with _$StatisticsDaoMixin {
|
|
|
|
|
StatisticsDao(super.db);
|
|
|
|
|
|
|
|
|
|
/// Получить сессию по ID
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<StudySession?> getSessionById(String id) {
|
2025-12-13 13:27:05 +00:00
|
|
|
return (select(studySessions)..where((s) => s.id.equals(id))).getSingleOrNull();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Получить сессию по sessionId
|
|
|
|
|
Future<StudySession?> getSessionBySessionId(String sessionId) {
|
|
|
|
|
return (select(studySessions)
|
|
|
|
|
..where((s) => s.sessionId.equals(sessionId))
|
|
|
|
|
).getSingleOrNull();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Получить активные сессии пользователя
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<List<StudySession>> getActiveSessions(String userId) {
|
2025-12-13 13:27:05 +00:00
|
|
|
return (select(studySessions)
|
|
|
|
|
..where((s) => s.userId.equals(userId))
|
|
|
|
|
..where((s) => s.endTime.isNull())
|
|
|
|
|
..orderBy([(s) => OrderingTerm.desc(s.startTime)])
|
|
|
|
|
).get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Получить сессии пользователя
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<List<StudySession>> getSessionsByUserId(String userId, {
|
2025-12-13 13:27:05 +00:00
|
|
|
int? limit,
|
|
|
|
|
int? offset,
|
|
|
|
|
DateTime? fromDate,
|
|
|
|
|
DateTime? toDate,
|
|
|
|
|
}) {
|
|
|
|
|
final query = select(studySessions)
|
|
|
|
|
..where((s) => s.userId.equals(userId))
|
|
|
|
|
..orderBy([(s) => OrderingTerm.desc(s.startTime)]);
|
|
|
|
|
|
|
|
|
|
if (fromDate != null) {
|
|
|
|
|
query.where((s) => s.startTime.isBiggerOrEqualValue(fromDate));
|
|
|
|
|
}
|
|
|
|
|
if (toDate != null) {
|
|
|
|
|
query.where((s) => s.startTime.isSmallerOrEqualValue(toDate));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (limit != null) {
|
|
|
|
|
query.limit(limit, offset: offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return query.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Создать сессию
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<String> createSession(StudySessionsCompanion session) async {
|
|
|
|
|
final inserted = await into(studySessions).insertReturning(session);
|
|
|
|
|
return inserted.id;
|
2025-12-13 13:27:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Обновить сессию
|
|
|
|
|
Future<bool> updateSession(StudySession session) {
|
|
|
|
|
return update(studySessions).replace(session);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Завершить сессию
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<void> endSession(String sessionId, {
|
2025-12-13 13:27:05 +00:00
|
|
|
int? wordsLearned,
|
|
|
|
|
int? testsCompleted,
|
|
|
|
|
double? accuracy,
|
|
|
|
|
}) {
|
|
|
|
|
final updates = StudySessionsCompanion(
|
|
|
|
|
id: Value(sessionId),
|
|
|
|
|
endTime: Value(DateTime.now()),
|
|
|
|
|
updatedAt: Value(DateTime.now()),
|
|
|
|
|
wordsLearned: wordsLearned != null ? Value(wordsLearned) : const Value.absent(),
|
|
|
|
|
testsCompleted: testsCompleted != null ? Value(testsCompleted) : const Value.absent(),
|
|
|
|
|
accuracy: accuracy != null ? Value(accuracy) : const Value.absent(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return (update(studySessions)..where((s) => s.id.equals(sessionId)))
|
|
|
|
|
.write(updates);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Подсчитать сессии пользователя
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<int> countSessionsByUserId(String userId) async {
|
2025-12-13 13:27:05 +00:00
|
|
|
final countExpr = studySessions.id.count();
|
|
|
|
|
final query = selectOnly(studySessions)
|
|
|
|
|
..addColumns([countExpr])
|
|
|
|
|
..where(studySessions.userId.equals(userId));
|
|
|
|
|
|
|
|
|
|
return await query.map((row) => row.read(countExpr)!).getSingle();
|
|
|
|
|
}
|
|
|
|
|
}
|