2025-12-13 13:27:05 +00:00
|
|
|
import 'package:drift/drift.dart';
|
2025-12-13 23:35:14 +00:00
|
|
|
import 'package:drift_postgres/drift_postgres.dart';
|
2025-12-13 13:27:05 +00:00
|
|
|
import '../database.dart';
|
|
|
|
|
import '../tables/statistics.dart';
|
|
|
|
|
import '../tables/users.dart';
|
2025-12-14 20:36:05 +00:00
|
|
|
import 'mixins/soft_delete_mixin.dart';
|
2025-12-13 13:27:05 +00:00
|
|
|
|
|
|
|
|
part 'statistics_dao.g.dart';
|
|
|
|
|
|
|
|
|
|
@DriftAccessor(tables: [StudySessions])
|
2025-12-20 18:26:15 +00:00
|
|
|
class StatisticsDao extends DatabaseAccessor<AppDatabase>
|
2025-12-14 20:36:05 +00:00
|
|
|
with _$StatisticsDaoMixin, SoftDeleteMixin<StudySessions, StudySession> {
|
2025-12-13 13:27:05 +00:00
|
|
|
StatisticsDao(super.db);
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
@override
|
|
|
|
|
TableInfo<StudySessions, StudySession> get table => studySessions;
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Получить сессию по ID (только активные)
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<StudySession?> getSessionById(String id) {
|
2025-12-14 20:36:05 +00:00
|
|
|
return getActiveById(id);
|
2025-12-13 13:27:05 +00:00
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Получить сессию по sessionId (только активные)
|
2025-12-13 13:27:05 +00:00
|
|
|
Future<StudySession?> getSessionBySessionId(String sessionId) {
|
2025-12-20 18:26:15 +00:00
|
|
|
return (selectActive()..where((s) => s.sessionId.equals(sessionId)))
|
|
|
|
|
.getSingleOrNull();
|
2025-12-13 13:27:05 +00:00
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Получить активные сессии пользователя (не завершенные и не удаленные)
|
2025-12-13 20:55:50 +00:00
|
|
|
Future<List<StudySession>> getActiveSessions(String userId) {
|
2025-12-14 20:36:05 +00:00
|
|
|
return (selectActive()
|
2025-12-20 18:26:15 +00:00
|
|
|
..where((s) => s.userId.equals(userId))
|
|
|
|
|
..where((s) => s.endTime.isNull())
|
|
|
|
|
..orderBy([(s) => OrderingTerm.desc(s.startTime)]))
|
|
|
|
|
.get();
|
2025-12-13 13:27:05 +00:00
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Получить сессии пользователя (только активные)
|
2025-12-20 18:26:15 +00:00
|
|
|
Future<List<StudySession>> getSessionsByUserId(
|
|
|
|
|
String userId, {
|
2025-12-13 13:27:05 +00:00
|
|
|
int? limit,
|
|
|
|
|
int? offset,
|
|
|
|
|
DateTime? fromDate,
|
|
|
|
|
DateTime? toDate,
|
|
|
|
|
}) {
|
2025-12-14 20:36:05 +00:00
|
|
|
final query = selectActive()
|
2025-12-13 13:27:05 +00:00
|
|
|
..where((s) => s.userId.equals(userId))
|
|
|
|
|
..orderBy([(s) => OrderingTerm.desc(s.startTime)]);
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-13 13:27:05 +00:00
|
|
|
if (fromDate != null) {
|
2025-12-20 18:26:15 +00:00
|
|
|
query.where(
|
|
|
|
|
(s) => s.startTime.isBiggerOrEqualValue(PgDateTime(fromDate)),
|
|
|
|
|
);
|
2025-12-13 13:27:05 +00:00
|
|
|
}
|
|
|
|
|
if (toDate != null) {
|
2025-12-13 23:35:14 +00:00
|
|
|
query.where((s) => s.startTime.isSmallerOrEqualValue(PgDateTime(toDate)));
|
2025-12-13 13:27:05 +00:00
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-13 13:27:05 +00:00
|
|
|
if (limit != null) {
|
|
|
|
|
query.limit(limit, offset: offset);
|
|
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-13 13:27:05 +00:00
|
|
|
return query.get();
|
|
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-13 13:27:05 +00:00
|
|
|
/// Создать сессию
|
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
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-13 13:27:05 +00:00
|
|
|
/// Обновить сессию
|
|
|
|
|
Future<bool> updateSession(StudySession session) {
|
|
|
|
|
return update(studySessions).replace(session);
|
|
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-13 13:27:05 +00:00
|
|
|
/// Завершить сессию
|
2025-12-20 18:26:15 +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),
|
2025-12-13 23:35:14 +00:00
|
|
|
endTime: Value(PgDateTime(DateTime.now())),
|
|
|
|
|
updatedAt: Value(PgDateTime(DateTime.now())),
|
2025-12-20 18:26:15 +00:00
|
|
|
wordsLearned: wordsLearned != null
|
|
|
|
|
? Value(wordsLearned)
|
|
|
|
|
: const Value.absent(),
|
|
|
|
|
testsCompleted: testsCompleted != null
|
|
|
|
|
? Value(testsCompleted)
|
|
|
|
|
: const Value.absent(),
|
2025-12-13 13:27:05 +00:00
|
|
|
accuracy: accuracy != null ? Value(accuracy) : const Value.absent(),
|
|
|
|
|
);
|
2025-12-20 18:26:15 +00:00
|
|
|
|
|
|
|
|
return (update(
|
|
|
|
|
studySessions,
|
|
|
|
|
)..where((s) => s.id.equals(sessionId))).write(updates);
|
2025-12-13 13:27:05 +00:00
|
|
|
}
|
2025-12-20 18:26:15 +00:00
|
|
|
|
2025-12-14 20:36:05 +00:00
|
|
|
/// Подсчитать сессии пользователя (только активные)
|
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])
|
2025-12-20 18:26:15 +00:00
|
|
|
..where(
|
|
|
|
|
studySessions.userId.equals(userId) &
|
|
|
|
|
studySessions.isDeleted.equals(false),
|
|
|
|
|
);
|
|
|
|
|
|
2025-12-13 13:27:05 +00:00
|
|
|
return await query.map((row) => row.read(countExpr)!).getSingle();
|
|
|
|
|
}
|
|
|
|
|
}
|