mnemo_cards/mnemo_cards_backend/lib/cron/tasks_seeder.dart
Dmitry 9c132174c5
Some checks are pending
Backend CI / test (push) Waiting to run
Backend 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
tasks
2025-12-14 01:16:53 +03:00

232 lines
8.9 KiB
Dart
Raw 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:mnemo_cards_backend/cron/task.dart' as cron_task;
import 'package:mnemo_cards_backend/database/database.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));
final tasks = [
// App Internal Tasks
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'],
),
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
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'],
),
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'],
),
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
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'],
),
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
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'],
),
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'],
),
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
// Используем InsertMode.insertOrIgnore для автоматического игнорирования дубликатов через ON CONFLICT
for (final taskModel in tasks) {
final rewardsJson = taskModel.rewards.map((r) => r.toJson()).toList();
await _db.into(_db.userTasks).insert(
UserTasksCompanion.insert(
title: taskModel.title,
description: taskModel.description,
type: taskModel.type,
difficulty: taskModel.difficulty,
status: taskModel.status,
rewards: Value(rewardsJson),
createdAt: Value(taskModel.createdAt),
expiresAt: taskModel.expiresAt,
completedAt: Value(taskModel.completedAt),
proofUrl: Value(taskModel.proofUrl),
instructions: Value(taskModel.instructions),
tags: Value(taskModel.tags),
imageUrl: Value(taskModel.imageUrl),
),
mode: InsertMode.insertOrIgnore, // ON CONFLICT DO NOTHING
);
}
print('Successfully seeded ${tasks.length} user tasks (duplicates ignored)');
} catch (e) {
print('Error seeding tasks: $e');
rethrow;
}
}
@override
int get intervalSeconds => 60 * 60 * 24; // Run once per day
}