feat: Add Nanaxe server with Docker, GitHub Actions CI/CD, and auto-deployment
- Add complete server infrastructure with Gitea, API, PostgreSQL - Implement Obsidian-compatible markdown mindmap converter - Add Flutter service for server synchronization - Configure GitHub Actions for automated build and deploy - Add production docker-compose with health checks - Include VPS setup and deployment scripts - Add comprehensive deployment documentation
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
// Тестирование DeepSeek сервиса в mock режиме
|
||||
// Запуск: dart run test_deepseek_mock.dart
|
||||
|
||||
|
||||
// Минимальные модели для теста
|
||||
enum TaskPriority { low, medium, high, urgent }
|
||||
|
||||
class TaskModel {
|
||||
final String id;
|
||||
final String title;
|
||||
final int estimatedHours;
|
||||
final TaskPriority priority;
|
||||
final DateTime? dueDate;
|
||||
|
||||
TaskModel({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.estimatedHours,
|
||||
required this.priority,
|
||||
this.dueDate,
|
||||
});
|
||||
}
|
||||
|
||||
void main() async {
|
||||
print('🧪 Тестирование DeepSeek сервиса (MOCK режим)\n');
|
||||
print('=' * 60);
|
||||
|
||||
// Импортируем сервис после определения моделей
|
||||
await runTests();
|
||||
}
|
||||
|
||||
Future<void> runTests() async {
|
||||
// Тест 1: Генерация подзадач
|
||||
print('\n📋 Тест 1: Генерация подзадач');
|
||||
print('-' * 60);
|
||||
final subtasks = mockGenerateSubtasks(
|
||||
title: 'Создать CRM систему',
|
||||
description: 'Разработка CRM для управления задачами команды',
|
||||
);
|
||||
print('✅ Сгенерировано подзадач: ${subtasks.length}');
|
||||
for (int i = 0; i < subtasks.length; i++) {
|
||||
final task = subtasks[i];
|
||||
print('\n${i + 1}. ${task['title']}');
|
||||
print(' ⏱️ Часы: ${task['estimatedHours']}');
|
||||
print(' 📄 ${task['description']}');
|
||||
}
|
||||
|
||||
// Тест 2: Приоритизация
|
||||
print('\n\n🎯 Тест 2: Приоритизация задачи');
|
||||
print('-' * 60);
|
||||
final urgentPriority = mockPrioritizeTask(
|
||||
dueDate: DateTime.now().add(Duration(hours: 12)),
|
||||
);
|
||||
print('Срочная задача (12 часов): ${urgentPriority.name.toUpperCase()}');
|
||||
|
||||
final mediumPriority = mockPrioritizeTask(
|
||||
dueDate: DateTime.now().add(Duration(days: 5)),
|
||||
);
|
||||
print('Средняя задача (5 дней): ${mediumPriority.name.toUpperCase()}');
|
||||
|
||||
final lowPriority = mockPrioritizeTask(
|
||||
dueDate: DateTime.now().add(Duration(days: 14)),
|
||||
);
|
||||
print('Низкий приоритет (14 дней): ${lowPriority.name.toUpperCase()}');
|
||||
|
||||
// Тест 3: Генерация описания
|
||||
print('\n\n✍️ Тест 3: Генерация описания');
|
||||
print('-' * 60);
|
||||
final description = mockGenerateDescription(
|
||||
'Интеграция с Google Calendar',
|
||||
'Синхронизация событий между CRM и календарем',
|
||||
);
|
||||
print('📝 Описание:\n$description');
|
||||
|
||||
// Тест 4: Умное планирование
|
||||
print('\n\n📅 Тест 4: Умное планирование');
|
||||
print('-' * 60);
|
||||
final tasks = [
|
||||
TaskModel(
|
||||
id: '1',
|
||||
title: 'Анализ',
|
||||
estimatedHours: 4,
|
||||
priority: TaskPriority.high),
|
||||
TaskModel(
|
||||
id: '2',
|
||||
title: 'Проектирование',
|
||||
estimatedHours: 6,
|
||||
priority: TaskPriority.high),
|
||||
TaskModel(
|
||||
id: '3',
|
||||
title: 'Разработка',
|
||||
estimatedHours: 12,
|
||||
priority: TaskPriority.medium),
|
||||
];
|
||||
final schedule = mockSchedule(
|
||||
tasks: tasks,
|
||||
startDate: DateTime.now(),
|
||||
endDate: DateTime.now().add(Duration(days: 7)),
|
||||
availableHoursPerDay: 6,
|
||||
);
|
||||
print('📊 Запланировано задач: ${schedule.length}');
|
||||
for (final item in schedule) {
|
||||
final task = tasks[item['taskId'] as int];
|
||||
print(
|
||||
' 📆 ${item['date'].toString().split(' ')[0]}: ${task.title} (${item['hours']}ч)');
|
||||
}
|
||||
|
||||
// Тест 5: Mind-карта
|
||||
print('\n\n🗺️ Тест 5: Генерация mind-карты');
|
||||
print('-' * 60);
|
||||
final mindMap = mockMindMap('CRM App');
|
||||
print('📊 Узлов в mind-карте: ${mindMap.length}');
|
||||
for (final node in mindMap) {
|
||||
final indent = ' ' * (node['level'] as int);
|
||||
final icon = node['level'] == 0 ? '📌' : '└';
|
||||
print('$indent$icon ${node['title']}');
|
||||
}
|
||||
|
||||
print('\n${'=' * 60}');
|
||||
print('✅ Все тесты пройдены! Mock режим работает отлично!');
|
||||
print('=' * 60);
|
||||
print('\n💡 Чтобы включить реальный API:');
|
||||
print(' 1. Пополните баланс на https://platform.deepseek.com/billing');
|
||||
print(
|
||||
' 2. В lib/core/deepseek_service.dart установите useMockMode = false');
|
||||
print('=' * 60);
|
||||
}
|
||||
|
||||
// Mock функции (копия из deepseek_service.dart)
|
||||
List<Map<String, dynamic>> mockGenerateSubtasks({
|
||||
required String title,
|
||||
required String description,
|
||||
}) {
|
||||
return [
|
||||
{
|
||||
'title': 'Анализ требований',
|
||||
'estimatedHours': 2,
|
||||
'description': 'Изучить требования и документацию'
|
||||
},
|
||||
{
|
||||
'title': 'Проектирование',
|
||||
'estimatedHours': 3,
|
||||
'description': 'Спроектировать архитектуру решения'
|
||||
},
|
||||
{'title': 'Реализация', 'estimatedHours': 8, 'description': 'Написать код'},
|
||||
{
|
||||
'title': 'Тестирование',
|
||||
'estimatedHours': 3,
|
||||
'description': 'Протестировать функциональность'
|
||||
},
|
||||
{
|
||||
'title': 'Документирование',
|
||||
'estimatedHours': 2,
|
||||
'description': 'Создать документацию'
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
TaskPriority mockPrioritizeTask({DateTime? dueDate}) {
|
||||
if (dueDate == null) return TaskPriority.medium;
|
||||
|
||||
final daysUntilDue = dueDate.difference(DateTime.now()).inDays;
|
||||
|
||||
if (daysUntilDue <= 1) return TaskPriority.urgent;
|
||||
if (daysUntilDue <= 3) return TaskPriority.high;
|
||||
if (daysUntilDue <= 7) return TaskPriority.medium;
|
||||
return TaskPriority.low;
|
||||
}
|
||||
|
||||
String mockGenerateDescription(String title, String? context) {
|
||||
final descriptions = {
|
||||
'Анализ требований':
|
||||
'Изучить и проанализировать все требования проекта. Подготовить документацию с детальным описанием функционала и ожиданий пользователей.',
|
||||
'Проектирование':
|
||||
'Разработать архитектуру решения, создать схемы базы данных и определить основные компоненты системы.',
|
||||
'Реализация':
|
||||
'Написать чистый, поддерживаемый код согласно лучшим практикам. Реализовать весь запланированный функционал.',
|
||||
'Тестирование':
|
||||
'Провести комплексное тестирование: модульные, интеграционные и end-to-end тесты для обеспечения качества.',
|
||||
'Деплой':
|
||||
'Подготовить инфраструктуру, настроить CI/CD пайплайн и развернуть приложение на production сервере.',
|
||||
};
|
||||
|
||||
return descriptions[title] ??
|
||||
'Задача: $title. ${context ?? "Выполнить в срок с надлежащим качеством."}';
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> mockSchedule({
|
||||
required List<TaskModel> tasks,
|
||||
required DateTime startDate,
|
||||
required DateTime endDate,
|
||||
required int availableHoursPerDay,
|
||||
}) {
|
||||
final schedule = <Map<String, dynamic>>[];
|
||||
var currentDate = startDate;
|
||||
var remainingHours = availableHoursPerDay;
|
||||
|
||||
for (var i = 0; i < tasks.length; i++) {
|
||||
if (currentDate.isAfter(endDate)) break;
|
||||
|
||||
final task = tasks[i];
|
||||
if (task.estimatedHours <= remainingHours) {
|
||||
schedule.add({
|
||||
'taskId': i,
|
||||
'date': currentDate,
|
||||
'hours': task.estimatedHours,
|
||||
});
|
||||
remainingHours -= task.estimatedHours;
|
||||
} else {
|
||||
currentDate = currentDate.add(const Duration(days: 1));
|
||||
remainingHours = availableHoursPerDay;
|
||||
|
||||
if (currentDate.isAfter(endDate)) break;
|
||||
|
||||
schedule.add({
|
||||
'taskId': i,
|
||||
'date': currentDate,
|
||||
'hours': task.estimatedHours > remainingHours
|
||||
? remainingHours
|
||||
: task.estimatedHours,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return schedule;
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> mockMindMap(String projectName) {
|
||||
return [
|
||||
{'level': 0, 'title': projectName, 'parentId': null},
|
||||
{'level': 1, 'title': 'Планирование', 'parentId': 0},
|
||||
{'level': 1, 'title': 'Разработка', 'parentId': 0},
|
||||
{'level': 1, 'title': 'Тестирование', 'parentId': 0},
|
||||
{'level': 1, 'title': 'Деплой', 'parentId': 0},
|
||||
{'level': 2, 'title': 'Анализ', 'parentId': 1},
|
||||
{'level': 2, 'title': 'Дизайн', 'parentId': 1},
|
||||
{'level': 2, 'title': 'Frontend', 'parentId': 2},
|
||||
{'level': 2, 'title': 'Backend', 'parentId': 2},
|
||||
{'level': 2, 'title': 'Unit тесты', 'parentId': 3},
|
||||
{'level': 2, 'title': 'E2E тесты', 'parentId': 3},
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user