cleaning root
Some checks reported errors
continuous-integration/drone/push Build encountered an error

This commit is contained in:
2025-09-11 08:18:31 +09:00
parent fcf27c1639
commit b0346e4bd7
26 changed files with 352 additions and 159 deletions

1
tools/__init__.py Normal file
View File

@@ -0,0 +1 @@
# Tools package

70
tools/check_fix.py Normal file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
"""
Простая проверка работы бота и исправленных методов
"""
import asyncio
import sys
import os
# Добавляем путь к проекту
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
from src.database.database import DatabaseManager
async def test_database():
"""Тестируем базу данных"""
print("🗄️ Тестируем подключение к базе данных...")
try:
db = DatabaseManager('data/quiz_bot.db')
await db.init_db()
# Проверяем статистику пользователя
stats = await db.get_user_stats(12345)
print(f"📊 Статистика пользователя: {stats}")
# Проверяем активную сессию
session = await db.get_active_session(12345)
print(f"🎯 Активная сессия: {session}")
print("✅ База данных работает корректно")
return True
except Exception as e:
print(f"❌ Ошибка базы данных: {e}")
return False
async def main():
"""Главная функция"""
print("=" * 50)
print("🔍 Проверка системы после исправлений")
print("=" * 50)
try:
# Тестируем базу данных
db_ok = await test_database()
if db_ok:
print("\nВсе компоненты работают корректно!")
print("🤖 Бот готов к использованию:")
print(" - База данных: OK")
print(" - Обработчики callback: исправлены")
print(" - Pydantic frozen instance: решено")
print("\n📱 Можете тестировать бота в Telegram: @testquiz11111_bot")
return 0
else:
print("\n❌ Обнаружены проблемы")
return 1
except Exception as e:
print(f"\n💥 Критическая ошибка: {e}")
return 1
if __name__ == "__main__":
exit_code = asyncio.run(main())
sys.exit(exit_code)

84
tools/demo.py Normal file
View File

@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""
Демонстрационный запуск Quiz Bot
Показывает структуру и возможности бота без реального токена
"""
import asyncio
import sys
import os
from pathlib import Path
# Добавляем путь к проекту
project_root = Path(__file__).parent
sys.path.append(str(project_root))
from config.config import config
from src.database.database import DatabaseManager
async def demo():
"""Демонстрация возможностей бота"""
print("🤖 Quiz Bot - Демонстрация")
print("=" * 50)
if not config.bot_token or config.bot_token == "your_bot_token_here":
print("⚠️ Токен бота не настроен!")
print("📝 Чтобы запустить бота:")
print(" 1. Создайте бота у @BotFather в Telegram")
print(" 2. Скопируйте токен в .env файл")
print(" 3. Запустите: python src/bot.py")
print()
# Проверяем базу данных
print("📊 Проверка базы данных...")
db = DatabaseManager(config.database_path)
# Получаем доступные тесты
tests = await db.get_tests_by_category()
print(f"✅ Найдено тестов: {len(tests)}")
for test in tests:
print(f" 📚 {test['name']} (Уровень {test['level']})")
print(f" {test['description']}")
# Показываем несколько вопросов из теста
questions = await db.get_random_questions(test['id'], 3)
print(f" Примеры вопросов ({len(questions)} из CSV файла):")
for i, q in enumerate(questions, 1):
print(f" {i}. {q['question']}")
print(f" 1) {q['option1']}")
print(f" 2) {q['option2']}")
print(f" 3) {q['option3']}")
print(f" 4) {q['option4']}")
print(f" Правильный: {q['correct_answer']}")
print()
print("🎮 Доступные режимы:")
print(f" 🎯 Гостевой режим: {'✅ Включен' if config.guest_mode_enabled else '❌ Отключен'}")
print(f" 📚 Режим тестирования: {'✅ Включен' if config.test_mode_enabled else '❌ Отключен'}")
print()
print("⚙️ Настройки:")
print(f" 📁 База данных: {config.database_path}")
print(f" 📁 CSV файлы: {config.csv_data_path}")
print(f" 🎲 Вопросов в тесте: {config.questions_per_quiz}")
print(f" ⏱️ Время на вопрос: {config.time_per_question} сек")
print("\n📱 Команды бота:")
commands = [
("/start", "Главное меню с выбором режима"),
("/help", "Справка по командам"),
("/stats", "Статистика пользователя"),
("/stop", "Остановить текущий тест")
]
for cmd, desc in commands:
print(f" {cmd} - {desc}")
print("\n🚀 Для запуска настоящего бота:")
print(" 1. Получите токен у @BotFather")
print(" 2. Добавьте BOT_TOKEN в файл .env")
print(" 3. Запустите: python src/bot.py")
if __name__ == "__main__":
asyncio.run(demo())

135
tools/demo_improvements.py Normal file
View File

@@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""
Демонстрация новой функциональности Quiz Bot
"""
import asyncio
import random
def demonstrate_shuffle_feature():
"""Демонстрация рандомизации ответов"""
print("🔄 ДЕМОНСТРАЦИЯ РАНДОМИЗАЦИИ ОТВЕТОВ")
print("=" * 50)
# Пример вопроса
original_question = {
'question': 'Как по-корейски "привет"?',
'option1': '안녕하세요', # Правильный ответ
'option2': '감사합니다',
'option3': '죄송합니다',
'option4': '안녕히가세요',
'correct_answer': 1
}
print(f"📝 Исходный вопрос: {original_question['question']}")
print(f"✅ Правильный ответ: {original_question['option1']} (позиция {original_question['correct_answer']})")
print()
# Симулируем перемешивание несколько раз
for i in range(3):
print(f"🎲 Попытка {i+1}:")
# Копируем исходные варианты
options = [
original_question['option1'],
original_question['option2'],
original_question['option3'],
original_question['option4']
]
correct_answer_text = options[original_question['correct_answer'] - 1]
# Перемешиваем
random.shuffle(options)
# Находим новую позицию
new_position = options.index(correct_answer_text) + 1
print(f" 1. {options[0]} {'' if new_position == 1 else ''}")
print(f" 2. {options[1]} {'' if new_position == 2 else ''}")
print(f" 3. {options[2]} {'' if new_position == 3 else ''}")
print(f" 4. {options[3]} {'' if new_position == 4 else ''}")
print(f" Правильный ответ теперь на позиции: {new_position}")
print()
def demonstrate_mode_differences():
"""Демонстрация различий между режимами"""
print("🎮 РАЗЛИЧИЯ МЕЖДУ РЕЖИМАМИ")
print("=" * 50)
print("🎯 ГОСТЕВОЙ РЕЖИМ:")
print(" ✅ Показывает правильный ответ")
print(" ⏸️ Требует нажатия 'Следующий вопрос'")
print(" 🎪 Развлекательная атмосфера")
print(" 📊 5 вопросов")
print(" 🔄 Варианты НЕ перемешиваются")
print()
print("📚 ТЕСТОВЫЙ РЕЖИМ:")
print("НЕ показывает правильный ответ")
print(" ⚡ Автоматический переход к следующему")
print(" 🎓 Серьезная атмосфера экзамена")
print(" 📊 10 вопросов")
print(" 🎲 Варианты перемешиваются каждый раз")
print()
def demonstrate_statistics():
"""Демонстрация новой статистики"""
print("📊 НОВАЯ РАСШИРЕННАЯ СТАТИСТИКА")
print("=" * 50)
# Пример статистики
stats_example = """📊 **Ваша статистика:**
📈 **Общие показатели:**
Всего вопросов: 87
✅ Правильных ответов: 65
🎯 Общая точность: 74.7%
🎪 Завершенных сессий: 9
🏆 Лучший результат: 95.0%
📊 Средний балл: 76.8%
🎮 **По режимам:**
🎯 Гостевые викторины: 4
📚 Серьезные тесты: 5
🏷️ **По категориям:**
📖 корейский: 7 попыток, 78.5% точность
📖 английский: 2 попытки, 65.0% точность
📈 **Последние результаты:**
📚 95.0% (19/20)
🎯 80.0% (4/5)
📚 75.0% (15/20)"""
print(stats_example)
print()
def main():
"""Главная функция демонстрации"""
print("🤖 QUIZ BOT - ДЕМОНСТРАЦИЯ НОВЫХ ВОЗМОЖНОСТЕЙ")
print("=" * 60)
print()
demonstrate_mode_differences()
demonstrate_shuffle_feature()
demonstrate_statistics()
print("🎉 ЗАКЛЮЧЕНИЕ")
print("=" * 50)
print("✅ Режим тестирования стал более серьезным")
print("✅ Рандомизация делает каждый тест уникальным")
print("✅ Статистика стала намного детальнее")
print("✅ Два режима для разных целей:")
print(" 🎯 Гостевой - для развлечения")
print(" 📚 Тестовый - для серьезного изучения")
print()
print("🚀 Бот готов к использованию: @testquiz11111_bot")
print("📱 Команды: /start, /help, /stats")
if __name__ == "__main__":
main()

65
tools/init_project.py Normal file
View File

@@ -0,0 +1,65 @@
import asyncio
import os
import sys
from pathlib import Path
# Добавляем корневую папку проекта в Python path
project_root = Path(__file__).parent.parent
sys.path.append(str(project_root))
from config.config import config
from src.database.database import DatabaseManager
from src.services.csv_service import QuizGenerator
async def init_project():
"""Инициализация проекта - создание БД и тестовых данных"""
print("🚀 Инициализация проекта Quiz Bot...")
# Создаем необходимые папки
os.makedirs(config.database_path.split('/')[0], exist_ok=True)
os.makedirs(config.csv_data_path, exist_ok=True)
# Инициализируем базу данных
print("📊 Инициализация базы данных...")
db = DatabaseManager(config.database_path)
await db.init_database()
print("✅ База данных готова!")
# Создаем тестовые CSV файлы
print("📝 Создание тестовых CSV файлов...")
await QuizGenerator.create_all_korean_csv_files(config.csv_data_path)
print("✅ CSV файлы созданы!")
# Загружаем тесты в базу данных
print("📚 Загрузка тестов в базу данных...")
levels_info = {
1: "Базовые слова и фразы",
2: "Повседневное общение",
3: "Средний уровень грамматики",
4: "Продвинутые конструкции",
5: "Высокий уровень языка"
}
for level in range(1, 6):
test_id = await db.add_test(
name=f"Корейский язык - Уровень {level}",
description=levels_info[level],
level=level,
category="korean",
csv_file=f"korean_level_{level}.csv"
)
print(f" ✅ Тест уровня {level} добавлен (ID: {test_id})")
print("\n🎉 Проект успешно инициализирован!")
print(f"📁 База данных: {config.database_path}")
print(f"📁 CSV файлы: {config.csv_data_path}")
print("\n📋 Следующие шаги:")
print("1. Скопируйте .env.example в .env")
print("2. Добавьте ваш BOT_TOKEN в .env файл")
print("3. Запустите бота командой: python src/bot.py")
if __name__ == "__main__":
asyncio.run(init_project())

50
tools/load_questions.py Normal file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""
Скрипт для загрузки вопросов из CSV файлов в базу данных
"""
import asyncio
import sys
import os
from pathlib import Path
# Добавляем путь к проекту
project_root = Path(__file__).parent
sys.path.append(str(project_root))
from config.config import config
from src.database.database import DatabaseManager
from src.services.csv_service import CSVQuizLoader
async def load_questions_to_db():
"""Загрузка вопросов из CSV файлов в базу данных"""
print("📚 Загрузка вопросов из CSV в базу данных...")
db = DatabaseManager(config.database_path)
csv_loader = CSVQuizLoader(config.csv_data_path)
# Получаем все тесты
tests = await db.get_tests_by_category()
for test in tests:
csv_file = test['csv_file']
test_id = test['id']
print(f" 📄 Загружаем {csv_file} для теста ID {test_id}")
# Загружаем вопросы из CSV
questions = await csv_loader.load_questions_from_csv(csv_file)
if questions:
# Добавляем вопросы в базу
success = await db.add_questions_to_test(test_id, questions)
if success:
print(f" ✅ Загружено {len(questions)} вопросов")
else:
print(f" ❌ Ошибка загрузки для теста {test_id}")
else:
print(f" ⚠️ Нет вопросов в файле {csv_file}")
print("✅ Загрузка завершена!")
if __name__ == "__main__":
asyncio.run(load_questions_to_db())

139
tools/setup.py Normal file
View File

@@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""
🚀 Quiz Bot - Финальная настройка и запуск
Этот скрипт поможет вам настроить и запустить телеграм-бота.
"""
import os
import sys
from pathlib import Path
def print_header():
print("🤖 Quiz Bot - Настройка и запуск")
print("=" * 50)
def check_token():
"""Проверка наличия токена бота"""
env_path = Path(".env")
if not env_path.exists():
print("❌ Файл .env не найден!")
print("📋 Создайте файл .env:")
print(" cp .env.example .env")
return False
# Читаем .env файл
with open(env_path, 'r') as f:
content = f.read()
if "BOT_TOKEN=your_bot_token_here" in content or "BOT_TOKEN=" in content:
return False
return True
def setup_instructions():
"""Инструкции по настройке"""
print("📋 Инструкции по настройке:")
print()
print("1. 🤖 Создание бота в Telegram:")
print(" - Найдите @BotFather в Telegram")
print(" - Отправьте команду /newbot")
print(" - Следуйте инструкциям")
print(" - Скопируйте токен (выглядит как: 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11)")
print()
print("2. ⚙️ Настройка файла .env:")
print(" - Откройте файл .env в текстовом редакторе")
print(" - Замените 'your_bot_token_here' на ваш токен")
print(" - Сохраните файл")
print()
print("3. 🚀 Запуск бота:")
print(" python src/bot.py")
print()
def project_status():
"""Статус проекта"""
print("📊 Статус проекта:")
# Проверяем структуру
required_files = [
"src/bot.py",
"src/database/database.py",
"src/services/csv_service.py",
"config/config.py",
"requirements.txt",
"data/quiz_bot.db"
]
missing_files = []
for file_path in required_files:
if not Path(file_path).exists():
missing_files.append(file_path)
if missing_files:
print("❌ Отсутствуют файлы:")
for file in missing_files:
print(f" - {file}")
return False
else:
print("Все необходимые файлы на месте")
# Проверяем CSV файлы
csv_files = list(Path("data").glob("*.csv"))
print(f"✅ Найдено CSV файлов: {len(csv_files)}")
# Проверяем базу данных
db_path = Path("data/quiz_bot.db")
if db_path.exists():
print(f"✅ База данных: {db_path} ({db_path.stat().st_size} байт)")
else:
print("❌ База данных не найдена")
return False
return True
def main():
print_header()
# Проверяем статус проекта
if not project_status():
print("\n❌ Проект не готов к запуску!")
print("🔧 Выполните инициализацию: python init_project.py")
return
print()
# Проверяем токен
if check_token():
print("✅ Токен бота настроен")
print()
print("🚀 Для запуска бота выполните:")
print(" python src/bot.py")
print()
print("🎮 Доступные команды в боте:")
print(" /start - Главное меню")
print(" /help - Справка")
print(" /stats - Статистика")
print(" /stop - Остановить тест")
print()
print("🎯 Режимы работы:")
print(" • Гостевой режим - быстрые викторины (5 вопросов)")
print(" • Тестирование - полные тесты (10 вопросов)")
print()
print("📚 Доступные тесты:")
print(" • Корейский язык (уровни 1-5)")
print(" • По 20 вопросов на каждый уровень")
else:
print("⚠️ Токен бота не настроен!")
setup_instructions()
print("\n🔧 Дополнительные утилиты:")
print(" python demo.py - Демонстрация возможностей")
print(" python test_quiz.py - Интерактивный тест в консоли")
print(" python load_questions.py - Перезагрузка вопросов в БД")
if __name__ == "__main__":
main()

178
tools/status.py Normal file
View File

@@ -0,0 +1,178 @@
#!/usr/bin/env python3
"""
Финальный отчет о состоянии Quiz Bot проекта
"""
import os
import sys
from pathlib import Path
# Добавляем путь к проекту
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
def print_banner():
print("🤖 QUIZ BOT - ФИНАЛЬНЫЙ ОТЧЕТ")
print("=" * 60)
def check_structure():
"""Проверка структуры проекта"""
print("📁 СТРУКТУРА ПРОЕКТА:")
required_structure = {
'src/bot.py': 'Основной файл бота',
'src/database/database.py': 'Менеджер базы данных',
'src/services/csv_service.py': 'Сервис загрузки CSV',
'config/config.py': 'Конфигурация',
'data/quiz_bot.db': 'База данных SQLite',
'requirements.txt': 'Зависимости Python',
'.env': 'Переменные окружения',
'README.md': 'Документация',
'Makefile': 'Команды автоматизации'
}
all_good = True
for file_path, description in required_structure.items():
if Path(file_path).exists():
print(f"{file_path:<30} - {description}")
else:
print(f"{file_path:<30} - {description}")
all_good = False
# Проверим CSV файлы
csv_files = list(Path("data").glob("*.csv"))
print(f" ✅ data/*.csv - {len(csv_files)} CSV файлов с тестами")
return all_good
def check_database():
"""Проверка базы данных"""
print("\n🗄️ БАЗА ДАННЫХ:")
try:
from src.database.database import DatabaseManager
from config.config import config
import asyncio
async def check():
db = DatabaseManager(config.database_path)
tests = await db.get_tests_by_category()
print(f" ✅ Подключение к БД работает")
print(f" ✅ Найдено тестов: {len(tests)}")
total_questions = 0
for test in tests:
questions = await db.get_random_questions(test['id'], 100)
total_questions += len(questions)
print(f" 📚 {test['name']}: {len(questions)} вопросов")
print(f"Всего вопросов в базе: {total_questions}")
asyncio.run(check())
return True
except Exception as e:
print(f" ❌ Ошибка БД: {e}")
return False
def check_config():
"""Проверка конфигурации"""
print("\n⚙️ КОНФИГУРАЦИЯ:")
try:
from config.config import config
# Проверяем токен
if config.bot_token and config.bot_token not in ['your_bot_token_here', 'test_token_for_demo_purposes']:
print(" ✅ BOT_TOKEN настроен")
bot_ready = True
else:
print(" ⚠️ BOT_TOKEN не настроен (нужен для реального запуска)")
bot_ready = False
print(f" ✅ DATABASE_PATH: {config.database_path}")
print(f" ✅ CSV_DATA_PATH: {config.csv_data_path}")
print(f" ✅ QUESTIONS_PER_QUIZ: {config.questions_per_quiz}")
print(f" ✅ GUEST_MODE_ENABLED: {config.guest_mode_enabled}")
print(f" ✅ TEST_MODE_ENABLED: {config.test_mode_enabled}")
return bot_ready
except Exception as e:
print(f" ❌ Ошибка конфигурации: {e}")
return False
def show_features():
"""Показать возможности"""
print("\n🎮 ВОЗМОЖНОСТИ:")
print(" 🎯 Гостевой режим - быстрые викторины (5 вопросов)")
print(" 📚 Режим тестирования - полные тесты (10 вопросов)")
print(" 📊 Система статистики и прогресса")
print(" 🇰🇷 100 вопросов по корейскому языку (5 уровней)")
print(" 📱 Команды: /start, /help, /stats, /stop")
print(" 🔄 Легкое добавление новых тестов через CSV")
def show_commands():
"""Показать команды"""
print("\n🚀 КОМАНДЫ ДЛЯ ЗАПУСКА:")
print(" make demo - Демонстрация без Telegram")
print(" make test - Интерактивный тест в консоли")
print(" make test-bot - Проверка импортов")
print(" make run - Запуск бота в Telegram")
print(" make help - Полная справка")
def show_instructions():
"""Инструкции по настройке"""
print("\n📋 ДЛЯ ЗАПУСКА РЕАЛЬНОГО БОТА:")
print(" 1. Найдите @BotFather в Telegram")
print(" 2. Создайте нового бота командой /newbot")
print(" 3. Скопируйте токен")
print(" 4. Откройте файл .env")
print(" 5. Замените BOT_TOKEN=... на ваш токен")
print(" 6. Запустите: make run")
def main():
print_banner()
# Проверяем структуру
structure_ok = check_structure()
# Проверяем базу данных
db_ok = check_database()
# Проверяем конфигурацию
config_ok = check_config()
# Показываем возможности
show_features()
# Показываем команды
show_commands()
print("\n" + "=" * 60)
if structure_ok and db_ok:
print("🎉 ПРОЕКТ ГОТОВ К ИСПОЛЬЗОВАНИЮ!")
if config_ok:
print("✅ Бот настроен и готов к запуску в Telegram!")
print("🚀 Команда: make run")
else:
print("⚠️ Нужно настроить токен для Telegram бота")
show_instructions()
print("\n🔧 Утилиты для тестирования:")
print(" make demo - Работает без токена")
print(" make test - Интерактивный режим")
else:
print("❌ ПРОЕКТ НЕ ГОТОВ!")
if not structure_ok:
print(" - Отсутствуют необходимые файлы")
if not db_ok:
print(" - Проблемы с базой данных")
print("=" * 60)
if __name__ == "__main__":
main()