mnemo_cards/mnemo_cards_backend/lib/cron/tasks_seeder.dart
Dmitry 0f49280805
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Mobile App CI / test (push) Waiting to run
Mobile App CI / build-android (push) Blocked by required conditions
Mobile App CI / build-ios (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Deploy Telegram Bot / Deploy Telegram Bot (push) Waiting to run
fixes and format
2025-12-20 21:26:15 +03:00

271 lines
11 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:drift/drift.dart';
import 'package:drift_postgres/drift_postgres.dart';
import 'package:mnemo_cards_backend/cron/task.dart' as cron_task;
import 'package:mnemo_cards_backend/database/database.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:mnemo_cards_common_backend/mnemo_cards_common_backend.dart';
class TasksSeederTask with cron_task.Task {
final AppDatabase _db;
TasksSeederTask(this._db);
@override
String get name => 'tasks_seeder';
@override
Future<void> task() async {
print('Seeding initial user tasks...');
try {
final now = DateTime.now();
final weekFromNow = now.add(const Duration(days: 7));
// Используем предопределенные UUID для каждой задачи
// Это позволяет избежать дубликатов при повторных запусках
final tasksWithIds = [
(
id: '00000000-0000-0000-0001-000000000001',
task: UserTaskModel(
title: 'Пройди 3 теста сегодня',
description:
'Заверши три тестовые сессии в приложении для улучшения навыков испанского.',
type: 'app_internal',
difficulty: 'easy',
rewards: [
TaskRewardModel(type: 'xp', amount: 50),
TaskRewardModel(type: 'coins', amount: 10),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow,
tags: ['tests', 'practice', 'daily'],
),
),
(
id: '00000000-0000-0000-0001-000000000002',
task: UserTaskModel(
title: 'Достигни 80% правильных ответов в тесте',
description:
'Пройди тест с результатом не менее 80% правильных ответов.',
type: 'app_internal',
difficulty: 'medium',
rewards: [
TaskRewardModel(type: 'xp', amount: 100),
TaskRewardModel(type: 'coins', amount: 25),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow,
tags: ['tests', 'accuracy', 'challenge'],
),
),
// External Tasks
(
id: '00000000-0000-0000-0001-000000000003',
task: UserTaskModel(
title: 'Подпишись на Telegram канал',
description:
'Подпишись на наш Telegram канал @mnemo_cards для получения обновлений и советов по изучению испанского.',
type: 'external',
difficulty: 'easy',
rewards: [
TaskRewardModel(type: 'xp', amount: 30),
TaskRewardModel(type: 'coins', amount: 5),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow,
tags: ['telegram', 'social', 'subscription'],
),
),
(
id: '00000000-0000-0000-0001-000000000004',
task: UserTaskModel(
title: 'Закажи еду на испанском',
description:
'Сделай заказ в ресторане или кафе, используя испанский язык. Запиши процесс на видео для подтверждения.',
type: 'external',
difficulty: 'hard',
rewards: [
TaskRewardModel(type: 'xp', amount: 200),
TaskRewardModel(type: 'coins', amount: 50),
TaskRewardModel(
type: 'achievement',
amount: 0,
achievementId: 'real_world_practice',
),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow.add(const Duration(days: 14)), // 3 weeks
instructions:
'Запиши видео, где ты делаешь заказ на испанском. Убедись, что официант понимает тебя.',
tags: ['speaking', 'restaurant', 'video', 'real_world'],
),
),
(
id: '00000000-0000-0000-0001-000000000005',
task: UserTaskModel(
title: 'Посмотри испанский фильм с субтитрами',
description:
'Посмотри испанский фильм или сериал с испанскими субтитрами в течение 30 минут.',
type: 'external',
difficulty: 'medium',
rewards: [
TaskRewardModel(type: 'xp', amount: 75),
TaskRewardModel(type: 'coins', amount: 15),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow,
tags: ['listening', 'media', 'subtitles'],
),
),
// Social Tasks
(
id: '00000000-0000-0000-0001-000000000006',
task: UserTaskModel(
title: 'Поделись прогрессом в соцсетях',
description:
'Поделись своим прогрессом в изучении испанского в социальных сетях с хэштегом #MnemoCards.',
type: 'social',
difficulty: 'easy',
rewards: [
TaskRewardModel(type: 'xp', amount: 40),
TaskRewardModel(type: 'coins', amount: 10),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow,
tags: ['social', 'sharing', 'progress'],
),
),
(
id: '00000000-0000-0000-0001-000000000007',
task: UserTaskModel(
title: 'Найди партнёра для практики',
description:
'Найди собеседника для практики испанского языка (друга, коллегу или через языковые приложения).',
type: 'social',
difficulty: 'medium',
rewards: [
TaskRewardModel(type: 'xp', amount: 90),
TaskRewardModel(type: 'coins', amount: 20),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow.add(const Duration(days: 7)), // 2 weeks
tags: ['conversation', 'partner', 'practice'],
),
),
// Additional App Tasks
(
id: '00000000-0000-0000-0001-000000000008',
task: UserTaskModel(
title: 'Изучай слова ежедневно 7 дней подряд',
description:
'Учи новые слова в приложении каждый день в течение недели.',
type: 'app_internal',
difficulty: 'hard',
rewards: [
TaskRewardModel(type: 'xp', amount: 150),
TaskRewardModel(type: 'coins', amount: 35),
TaskRewardModel(
type: 'achievement',
amount: 0,
achievementId: 'consistency_master',
),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow.add(const Duration(days: 21)), // 4 weeks
tags: ['vocabulary', 'daily', 'streak', 'consistency'],
),
),
(
id: '00000000-0000-0000-0001-000000000009',
task: UserTaskModel(
title: 'Пройди тест по грамматике',
description:
'Заверши специализированный тест по грамматике испанского языка.',
type: 'app_internal',
difficulty: 'medium',
rewards: [
TaskRewardModel(type: 'xp', amount: 80),
TaskRewardModel(type: 'coins', amount: 20),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow,
tags: ['grammar', 'tests', 'knowledge'],
),
),
(
id: '00000000-0000-0000-0001-000000000010',
task: UserTaskModel(
title: 'Практикуй произношение',
description:
'Заверши урок по произношению или запиши себя, читая текст на испанском.',
type: 'app_internal',
difficulty: 'easy',
rewards: [
TaskRewardModel(type: 'xp', amount: 60),
TaskRewardModel(type: 'coins', amount: 12),
],
status: 'available',
createdAt: now,
expiresAt: weekFromNow,
tags: ['pronunciation', 'speaking', 'practice'],
),
),
];
// Convert UserTaskModel to UserTasksCompanion and insert через DAO
// Используем предопределенные UUID для идемпотентности seeder'а
int insertedCount = 0;
int skippedCount = 0;
for (final taskData in tasksWithIds) {
final taskModel = taskData.task;
final rewardsJson = taskModel.rewards.map((r) => r.toJson()).toList();
final companion = UserTasksCompanion.insert(
id: Value(
taskData.id,
), // Предопределенный UUID для идемпотентности seeder'а
title: taskModel.title,
description: taskModel.description,
type: taskModel.type,
difficulty: taskModel.difficulty,
status: taskModel.status,
rewards: Value(rewardsJson),
createdAt: Value(PgDateTime(taskModel.createdAt)),
expiresAt: PgDateTime(taskModel.expiresAt),
completedAt: Value(taskModel.completedAt?.let(PgDateTime.new)),
proofUrl: Value(taskModel.proofUrl),
instructions: Value(taskModel.instructions),
tags: Value(taskModel.tags),
imageUrl: Value(taskModel.imageUrl),
);
final wasCreated = await _db.taskDao.createUserTaskOrIgnore(companion);
if (wasCreated) {
insertedCount++;
} else {
skippedCount++;
}
}
print(
'Successfully seeded user tasks: $insertedCount inserted, $skippedCount skipped (already exist)',
);
} catch (e) {
print('Error seeding tasks: $e');
rethrow;
}
}
@override
int get intervalSeconds => 60 * 60 * 24; // Run once per day
}