Разработка программного модуля информационной системы «Игра «Собачья академия» #3
3
.idea/misc.xml
generated
|
|
@ -4,4 +4,7 @@
|
||||||
<option name="sdkName" value="Python 3.13 (Dog_Academy)" />
|
<option name="sdkName" value="Python 3.13 (Dog_Academy)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
|
||||||
|
<component name="PyPackaging">
|
||||||
|
<option name="earlyReleasesAsUpgrades" value="true" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
BIN
assets/background.png
Normal file
|
After Width: | Height: | Size: 821 KiB |
BIN
assets/bone.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
assets/dogs/Chihuahua.png
Normal file
|
After Width: | Height: | Size: 326 KiB |
BIN
assets/dogs/Corgi.png
Normal file
|
After Width: | Height: | Size: 253 KiB |
BIN
assets/dogs/Golden_Retriever.png
Normal file
|
After Width: | Height: | Size: 215 KiB |
BIN
assets/dogs/Husky.png
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
assets/dogs/Pomeranian.png
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
assets/dogs/Pug.png
Normal file
|
After Width: | Height: | Size: 255 KiB |
BIN
assets/dogs/Yorkshire_Terrier.png
Normal file
|
After Width: | Height: | Size: 341 KiB |
BIN
assets/done.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
assets/lock.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
assets/logo.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
assets/settings.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
assets/unlock.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
123
config.py
|
|
@ -1,6 +1,21 @@
|
||||||
# config.py
|
import os
|
||||||
|
|
||||||
# Интерфейс
|
# Базовая директория проекта
|
||||||
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# Директория с ресурсами
|
||||||
|
ASSETS_DIR = os.path.join(BASE_DIR, "assets")
|
||||||
|
DOGS_DIR = os.path.join(ASSETS_DIR, "dogs")
|
||||||
|
|
||||||
|
# Админ-интерфейс (тёмные цвета)
|
||||||
|
ADMIN_BACKGROUND_COLOR = "#403d49"
|
||||||
|
ADMIN_PRIMARY_COLOR = "#ff6347"
|
||||||
|
ADMIN_BUTTON_COLOR = "#444444"
|
||||||
|
ADMIN_BUTTON_TEXT_COLOR = "#ffffff"
|
||||||
|
ADMIN_FONT = ("Comic Sans MS", 25)
|
||||||
|
ADMIN_BIG_FONT = ("Comic Sans MS", 40)
|
||||||
|
|
||||||
|
# Интерфейс пользователя (АВТОРИЗАЦИЯ)
|
||||||
BACKGROUND_COLOR = "#f8e1e1"
|
BACKGROUND_COLOR = "#f8e1e1"
|
||||||
PRIMARY_COLOR = "#ff6347"
|
PRIMARY_COLOR = "#ff6347"
|
||||||
BUTTON_COLOR = "#87ceeb"
|
BUTTON_COLOR = "#87ceeb"
|
||||||
|
|
@ -8,9 +23,111 @@ BUTTON_TEXT_COLOR = "white"
|
||||||
FONT = ("Comic Sans MS", 25)
|
FONT = ("Comic Sans MS", 25)
|
||||||
BIG_FONT = ("Comic Sans MS", 40)
|
BIG_FONT = ("Comic Sans MS", 40)
|
||||||
|
|
||||||
|
# ГЛАВНОЕ МЕНЮ
|
||||||
|
BACKGROUND_COLOR_USER = "#bcabe5" # Основной фон
|
||||||
|
TOP_PANEL_COLOR_USER = "#aa9bcd" # Цвет верхней панели
|
||||||
|
BUTTON_COLOR_PROFILE_USER = "#a2c792" # Цвет кнопок "Профиль", "Магазин", "База знаний"
|
||||||
|
BUTTON_COLOR_PLAY_USER = "#b4e1a1" # Цвет кнопки "Играть"
|
||||||
|
BUTTON_COLOR_EXIT_USER = "#a2c792" # Цвет кнопки "Выход"
|
||||||
|
BUTTON_TEXT_COLOR_USER = "white" # Цвет текста на кнопках
|
||||||
|
FONT_USER = ("Comic Sans MS", 20) # Шрифт для текста кнопок
|
||||||
|
BIG_FONT_USER = ("Comic Sans MS", 30) # Большой шрифт (например, для заголовков)
|
||||||
|
BUTTON_RADIUS_USER = 50 # Радиус круглой кнопки
|
||||||
|
EXIT_BUTTON_SIZE_USER = (80, 40) # Размер кнопки "Выход"
|
||||||
|
TOP_PANEL_COLOR = "#BBA0D0"
|
||||||
|
BUTTON_COLOR_PROFILE = "#8FC085"
|
||||||
|
BUTTON_COLOR_PLAY = "#8FC085"
|
||||||
|
BUTTON_COLOR_EXIT = "#8FC085"
|
||||||
|
# Размеры
|
||||||
|
PLAY_BUTTON_RADIUS = 100
|
||||||
|
EXIT_BUTTON_WIDTH = 100
|
||||||
|
EXIT_BUTTON_HEIGHT = 50
|
||||||
|
|
||||||
# Данные для авторизации администратора
|
# Данные для авторизации администратора
|
||||||
ADMIN_LOGIN = "admin"
|
ADMIN_LOGIN = "admin"
|
||||||
ADMIN_PASSWORD = "admin123"
|
ADMIN_PASSWORD = "admin123"
|
||||||
|
|
||||||
# База данных
|
# База данных
|
||||||
DATABASE_URL = "sqlite:///database/DogAcademy.db" # Обновлено на правильный путь
|
DATABASE_URL = f"sqlite:///{os.path.join(BASE_DIR, 'database', 'DogAcademy.db')}"
|
||||||
|
|
||||||
|
# Пути к ресурсам
|
||||||
|
SETTINGS_IMG = os.path.join(ASSETS_DIR, "settings.png")
|
||||||
|
LOGO = os.path.join(ASSETS_DIR, "logo.png")
|
||||||
|
BACKGROUND_GAME = os.path.join(ASSETS_DIR, "background.png")
|
||||||
|
BONE = os.path.join(ASSETS_DIR, "bone.png")
|
||||||
|
LOCK = os.path.join(ASSETS_DIR, "lock.png")
|
||||||
|
UNLOCK = os.path.join(ASSETS_DIR, "unlock.png")
|
||||||
|
DONE = os.path.join(ASSETS_DIR, "done.png")
|
||||||
|
|
||||||
|
# Пути к изображениям собак
|
||||||
|
CHIHUAHUA = os.path.join(DOGS_DIR, "Chihuahua.png")
|
||||||
|
CORGI = os.path.join(DOGS_DIR, "Corgi.png")
|
||||||
|
RETRIEVER = os.path.join(DOGS_DIR, "Golden_Retriever.png")
|
||||||
|
HUSKY = os.path.join(DOGS_DIR, "Husky.png")
|
||||||
|
POMERANIAN = os.path.join(DOGS_DIR, "Pomeranian.png")
|
||||||
|
PUG = os.path.join(DOGS_DIR, "Pug.png")
|
||||||
|
YORKSHIRE = os.path.join(DOGS_DIR, "Yorkshire_Terrier.png")
|
||||||
|
|
||||||
|
# Данные о характерах собак
|
||||||
|
DOG_CHARACTERS = {
|
||||||
|
"Chihuahua": {
|
||||||
|
"image": CHIHUAHUA,
|
||||||
|
"speed": 8,
|
||||||
|
"endurance": 5,
|
||||||
|
"special_ability": "Fast Dodge",
|
||||||
|
},
|
||||||
|
"Corgi": {
|
||||||
|
"image": CORGI,
|
||||||
|
"speed": 6,
|
||||||
|
"endurance": 7,
|
||||||
|
"special_ability": "Extra Jump",
|
||||||
|
},
|
||||||
|
"Golden Retriever": {
|
||||||
|
"image": RETRIEVER,
|
||||||
|
"speed": 7,
|
||||||
|
"endurance": 8,
|
||||||
|
"special_ability": "Bonus Points",
|
||||||
|
},
|
||||||
|
"Husky": {
|
||||||
|
"image": HUSKY,
|
||||||
|
"speed": 9,
|
||||||
|
"endurance": 6,
|
||||||
|
"special_ability": "Speed Boost",
|
||||||
|
},
|
||||||
|
"Pomeranian": {
|
||||||
|
"image": POMERANIAN,
|
||||||
|
"speed": 7,
|
||||||
|
"endurance": 4,
|
||||||
|
"special_ability": "Charm",
|
||||||
|
},
|
||||||
|
"Pug": {
|
||||||
|
"image": PUG,
|
||||||
|
"speed": 5,
|
||||||
|
"endurance": 9,
|
||||||
|
"special_ability": "Resilience",
|
||||||
|
},
|
||||||
|
"Yorkshire Terrier": {
|
||||||
|
"image": YORKSHIRE,
|
||||||
|
"speed": 6,
|
||||||
|
"endurance": 5,
|
||||||
|
"special_ability": "Quick Recovery",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Утилиты
|
||||||
|
NOTIFICATION_LEVEL = "info" # Возможные значения: "info", "warning", "error"
|
||||||
|
USE_DATABASE_LOGS = True
|
||||||
|
|
||||||
|
# Игровые параметры
|
||||||
|
INITIAL_SCORE = 5 # Начальные очки игрока
|
||||||
|
POINTS_CORRECT_ANSWER = 2 # Очки за правильный ответ
|
||||||
|
POINTS_WRONG_ANSWER = -1 # Штраф за неправильный ответ
|
||||||
|
MAX_LEVELS = 100 # Максимальное количество уровней
|
||||||
|
INITIAL_DOG_STATUS = {"health": 100, "hunger": 0, "sleepiness": 0} # Стартовые характеристики собаки
|
||||||
|
|
||||||
|
# Параметры карты
|
||||||
|
MIN_OBSTACLES = 3 # Минимум препятствий на уровне
|
||||||
|
MAX_OBSTACLES = 6 # Максимум препятствий на уровне
|
||||||
|
|
||||||
|
# Графика и анимация
|
||||||
|
COUNTDOWN_DURATION = 3 # Продолжительность обратного отсчёта в секундах
|
||||||
|
|
@ -1,28 +1,445 @@
|
||||||
|
import logging
|
||||||
|
from sqlalchemy import func
|
||||||
|
from sqlalchemy.orm import joinedload
|
||||||
from database.db_session import get_session
|
from database.db_session import get_session
|
||||||
from database.models import Auth
|
from database.models import Auth, Notifications, Users, GameSession, Dogs, Questions
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
def create_user(login, password):
|
|
||||||
"""Создание нового пользователя в базе данных."""
|
def get_user_by_id(user_id):
|
||||||
|
"""Получение данных пользователя по ID с предварительной загрузкой связанных данных."""
|
||||||
session = get_session()
|
session = get_session()
|
||||||
try:
|
try:
|
||||||
new_user = Auth(login=login, password=password)
|
user = (
|
||||||
|
session.query(Users)
|
||||||
|
.options(joinedload(Users.game_sessions)) # Предзагрузка связанных игровых сессий
|
||||||
|
.filter_by(user_id=user_id)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
return user
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
logging.error(f"Ошибка при получении пользователя: {e}")
|
||||||
|
return None
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def create_user(login, password, username):
|
||||||
|
"""Регистрация нового пользователя."""
|
||||||
|
session = get_session()
|
||||||
|
|
||||||
|
# Проверка, есть ли уже пользователь с таким логином
|
||||||
|
if session.query(Auth).filter_by(login=login).first():
|
||||||
|
return False, "Логин уже используется."
|
||||||
|
|
||||||
|
# Создание новой записи в таблице Auth
|
||||||
|
new_auth = Auth(login=login, password=password)
|
||||||
|
session.add(new_auth)
|
||||||
|
|
||||||
|
try:
|
||||||
|
session.commit() # Сохранение изменений в таблице Auth
|
||||||
|
|
||||||
|
# Создание новой записи в таблице Users, связываем с только что добавленным Auth
|
||||||
|
new_user = Users(user_id=new_auth.user_id, username=username)
|
||||||
session.add(new_user)
|
session.add(new_user)
|
||||||
|
session.commit() # Сохраняем изменения в таблице Users
|
||||||
|
|
||||||
|
# Создаём новый игровой процесс для этого пользователя
|
||||||
|
new_game_session = GameSession(user_id=new_user.user_id, level=1) # Устанавливаем уровень по умолчанию
|
||||||
|
session.add(new_game_session)
|
||||||
|
session.commit() # Сохраняем данные в GameSession
|
||||||
|
|
||||||
|
print(f"Пользователь {username} успешно добавлен!")
|
||||||
|
return True, "Регистрация успешна."
|
||||||
|
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback() # Откат изменений при ошибке
|
||||||
|
print(f"Ошибка при создании пользователя: {e}")
|
||||||
|
return False, "Произошла ошибка при регистрации."
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def check_user(login, password=None):
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
query = session.query(Auth).filter_by(login=login)
|
||||||
|
if password:
|
||||||
|
query = query.filter_by(password=password)
|
||||||
|
user = query.first()
|
||||||
|
if user:
|
||||||
|
return user.user_id
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при проверке пользователя: {e}")
|
||||||
|
return None
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def save_progress(user_id, level, score, duration, health, hunger, sleepiness):
|
||||||
|
"""Сохранение игрового прогресса в базу данных."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
if not user_id:
|
||||||
|
raise ValueError("user_id не указан!")
|
||||||
|
session_data = GameSession(
|
||||||
|
user_id=user_id,
|
||||||
|
level=level,
|
||||||
|
score=score,
|
||||||
|
duration=duration,
|
||||||
|
health=health,
|
||||||
|
hunger=hunger,
|
||||||
|
sleepiness=sleepiness,
|
||||||
|
end_time=func.now()
|
||||||
|
)
|
||||||
|
session.add(session_data)
|
||||||
session.commit()
|
session.commit()
|
||||||
except SQLAlchemyError as e:
|
except SQLAlchemyError as e:
|
||||||
print(f"Ошибка при создании пользователя: {e}")
|
logging.error(f"Ошибка при сохранении прогресса: {e}")
|
||||||
|
session.rollback()
|
||||||
|
except ValueError as e:
|
||||||
|
logging.error(e)
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def get_user_progress(user_id):
|
||||||
|
"""Получение игрового прогресса пользователя."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
return session.query(GameSession).filter_by(user_id=user_id).all()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Ошибка при получении прогресса пользователя: {e}")
|
||||||
|
return []
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def create_notification(user_id, message):
|
||||||
|
"""Создание уведомления для пользователя."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
notification = Notifications(user_id=user_id, message=message)
|
||||||
|
session.add(notification)
|
||||||
|
session.commit()
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при создании уведомления: {e}")
|
||||||
session.rollback()
|
session.rollback()
|
||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
def check_user(login, password):
|
def get_notifications(user_id):
|
||||||
"""Проверка данных пользователя для авторизации."""
|
"""Получение уведомлений для пользователя."""
|
||||||
session = get_session()
|
session = get_session()
|
||||||
try:
|
try:
|
||||||
user = session.query(Auth).filter_by(login=login, password=password).first()
|
notifications = session.query(Notifications).filter_by(user_id=user_id).all()
|
||||||
return user is not None
|
return notifications
|
||||||
except SQLAlchemyError as e:
|
except SQLAlchemyError as e:
|
||||||
print(f"Ошибка при проверке пользователя: {e}")
|
print(f"Ошибка при получении уведомлений: {e}")
|
||||||
return False
|
return []
|
||||||
finally:
|
finally:
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
|
def get_knowledge_base():
|
||||||
|
"""Получение базы знаний (статей о собаках)."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
dogs = session.query(Dogs).all()
|
||||||
|
return dogs # Список объектов Dogs
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при получении базы знаний: {e}")
|
||||||
|
return []
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def get_dogs():
|
||||||
|
"""Получение списка пород собак."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
dogs = session.query(Dogs).all()
|
||||||
|
return dogs # Список объектов Dogs
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при получении списка собак: {e}")
|
||||||
|
return []
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def update_user_dog(user_id, dog_id):
|
||||||
|
"""Обновление выбранной пользователем породы собаки."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
user = session.query(Users).filter_by(user_id=user_id).first()
|
||||||
|
if user:
|
||||||
|
user.dog_id = dog_id
|
||||||
|
session.commit()
|
||||||
|
print(f"Порода пользователя обновлена на {dog_id}")
|
||||||
|
else:
|
||||||
|
print("Пользователь не найден.")
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при обновлении породы собаки: {e}")
|
||||||
|
session.rollback()
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def debug_list_users():
|
||||||
|
"""Отладочный вывод всех пользователей."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
users = session.query(Auth).all()
|
||||||
|
for user in users:
|
||||||
|
print(f"User ID: {user.user_id}, Login: {user.login}, Password: {user.password}")
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при получении списка пользователей: {e}")
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def get_all_users():
|
||||||
|
"""Получить всех пользователей с предварительной загрузкой данных."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
users = session.query(Users).options(joinedload(Users.auth)).all()
|
||||||
|
return users
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при получении пользователей: {e}")
|
||||||
|
return [] # Возвращаем пустой список, если ошибка
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def get_all_questions():
|
||||||
|
"""Получить все вопросы."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
questions = session.query(Questions).all()
|
||||||
|
return questions
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при получении вопросов: {e}")
|
||||||
|
return []
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def get_all_dogs():
|
||||||
|
"""Получить все записи о собаках."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
dogs = session.query(Dogs).all() # Запрос к базе данных для получения всех собак
|
||||||
|
return dogs
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при получении собак: {e}")
|
||||||
|
return []
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def get_user_by_username(username):
|
||||||
|
"""Получить пользователя по логину."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
user = session.query(Users).join(Auth).filter(Auth.login == username).first()
|
||||||
|
return user
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при получении пользователя: {e}")
|
||||||
|
return None
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def update_user(user_id, new_login, new_password):
|
||||||
|
"""Обновить данные пользователя."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
user = session.query(Users).filter_by(user_id=user_id).first()
|
||||||
|
if user:
|
||||||
|
auth = user.auth
|
||||||
|
auth.login = new_login
|
||||||
|
auth.password = new_password
|
||||||
|
session.commit()
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при обновлении пользователя: {e}")
|
||||||
|
session.rollback()
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def update_user_info(user_id, new_login, new_username):
|
||||||
|
"""Обновление данных пользователя."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
user = session.query(Users).filter_by(user_id=user_id).first()
|
||||||
|
if user:
|
||||||
|
user.auth.login = new_login
|
||||||
|
user.username = new_username
|
||||||
|
session.commit()
|
||||||
|
return True, "Данные пользователя обновлены."
|
||||||
|
return False, "Пользователь не найден."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
return False, f"Ошибка при обновлении: {e}"
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
def delete_user(user_id):
|
||||||
|
"""Удаление пользователя по ID, включая связанные записи."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
# Находим пользователя
|
||||||
|
user = session.query(Users).filter_by(user_id=user_id).first()
|
||||||
|
if not user:
|
||||||
|
return False, "Пользователь не найден."
|
||||||
|
|
||||||
|
# Удаляем запись из Auth
|
||||||
|
auth = user.auth
|
||||||
|
if auth:
|
||||||
|
session.delete(auth)
|
||||||
|
|
||||||
|
# Удаляем запись из Users
|
||||||
|
session.delete(user)
|
||||||
|
|
||||||
|
# Фиксируем изменения
|
||||||
|
session.commit()
|
||||||
|
return True, "Пользователь успешно удалён."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
return False, f"Ошибка при удалении пользователя: {e}"
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update_dog_info(dog_id, breed, characteristics):
|
||||||
|
"""Обновление информации о собаке."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
dog = session.query(Dogs).filter_by(dog_id=dog_id).first()
|
||||||
|
if dog:
|
||||||
|
dog.breed = breed
|
||||||
|
dog.characteristics = characteristics
|
||||||
|
session.commit()
|
||||||
|
return True, "Информация о собаке обновлена."
|
||||||
|
return False, "Собака не найдена."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
return False, f"Ошибка при обновлении: {e}"
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
def update_question(question_id, text, helpful_info):
|
||||||
|
"""Обновление вопроса."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
question = session.query(Questions).filter_by(question_id=question_id).first()
|
||||||
|
if question:
|
||||||
|
question.question_text = text
|
||||||
|
question.helpful_info = helpful_info
|
||||||
|
session.commit()
|
||||||
|
return True, "Вопрос обновлён."
|
||||||
|
return False, "Вопрос не найден."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
return False, f"Ошибка при обновлении: {e}"
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def update_user_level(user_id, new_level):
|
||||||
|
"""Обновляет уровень пользователя в базе данных."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
user = session.query(Users).filter_by(user_id=user_id).first()
|
||||||
|
if user and user.level < new_level:
|
||||||
|
user.level = new_level
|
||||||
|
session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
session.rollback()
|
||||||
|
logging.error(f"Ошибка при обновлении уровня пользователя: {e}")
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def add_user_to_db(user_data):
|
||||||
|
"""
|
||||||
|
Добавление нового пользователя в базу данных.
|
||||||
|
Создаёт записи в таблицах Auth и Users.
|
||||||
|
"""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
# Создание записи в таблице Auth
|
||||||
|
new_auth = Auth(
|
||||||
|
login=user_data['login'],
|
||||||
|
password=user_data['password']
|
||||||
|
)
|
||||||
|
session.add(new_auth)
|
||||||
|
session.flush() # Сохраняем, чтобы получить user_id для Users
|
||||||
|
|
||||||
|
# Создание записи в таблице Users, связываем с Auth
|
||||||
|
new_user = Users(
|
||||||
|
user_id=new_auth.user_id, # Используем внешний ключ
|
||||||
|
username=user_data['username'],
|
||||||
|
level=user_data.get('level', 1), # Уровень по умолчанию 1
|
||||||
|
achievement=user_data.get('achievement', None) # По умолчанию пусто
|
||||||
|
)
|
||||||
|
session.add(new_user)
|
||||||
|
session.commit()
|
||||||
|
print(f"Пользователь {user_data['username']} успешно добавлен.")
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
print(f"Ошибка при добавлении пользователя: {e}")
|
||||||
|
raise # Пробрасываем исключение для обработки
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
def add_question_to_db(question_data):
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
new_question = Questions(**question_data)
|
||||||
|
session.add(new_question)
|
||||||
|
session.commit()
|
||||||
|
print(f"Вопрос успешно добавлен: {question_data['question_text']}")
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при добавлении вопроса: {e}")
|
||||||
|
session.rollback()
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def add_dog_to_db(dog_data):
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
new_dog = Dogs(**dog_data)
|
||||||
|
session.add(new_dog)
|
||||||
|
session.commit()
|
||||||
|
print(f"Собака успешно добавлена: {dog_data['breed']}")
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
print(f"Ошибка при добавлении собаки: {e}")
|
||||||
|
session.rollback()
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def delete_dog(dog_id):
|
||||||
|
"""Удаление породы собак по ID."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
dog = session.query(Dogs).filter_by(dog_id=dog_id).first()
|
||||||
|
if dog:
|
||||||
|
session.delete(dog)
|
||||||
|
session.commit()
|
||||||
|
print(f"Порода с ID {dog_id} успешно удалена.")
|
||||||
|
return True, "Порода успешно удалена."
|
||||||
|
return False, "Порода не найдена."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
return False, f"Ошибка при удалении: {e}"
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
def delete_question(question_id):
|
||||||
|
"""Удаление вопроса по ID."""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
question = session.query(Questions).filter_by(question_id=question_id).first()
|
||||||
|
if question:
|
||||||
|
session.delete(question)
|
||||||
|
session.commit()
|
||||||
|
return True, "Вопрос успешно удалён."
|
||||||
|
return False, "Вопрос не найден."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
return False, f"Ошибка при удалении: {e}"
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
# database/db_session.py
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from config import DATABASE_URL
|
from config import DATABASE_URL
|
||||||
|
|
@ -9,16 +8,42 @@ import os
|
||||||
engine = create_engine(DATABASE_URL, echo=True)
|
engine = create_engine(DATABASE_URL, echo=True)
|
||||||
|
|
||||||
# Создание фабрики сессий
|
# Создание фабрики сессий
|
||||||
Session = sessionmaker(bind=engine)
|
Session = sessionmaker(bind=engine, autoflush=True)
|
||||||
|
|
||||||
def init_db():
|
# Переменная для хранения текущей сессии
|
||||||
"""Инициализация базы данных: создание файла и таблиц."""
|
current_session = None
|
||||||
if not os.path.exists("database/DogAcademy.db"):
|
|
||||||
print("База данных не найдена. Создаём новую...")
|
def create_session():
|
||||||
Base.metadata.create_all(bind=engine)
|
"""Создание сессии для работы с базой данных."""
|
||||||
|
return Session()
|
||||||
|
|
||||||
|
def init_db(refresh=False):
|
||||||
|
"""
|
||||||
|
Инициализация базы данных: создание файла и таблиц.
|
||||||
|
Если `refresh` равно True, удаляет и пересоздаёт таблицы.
|
||||||
|
"""
|
||||||
|
global current_session
|
||||||
|
if not os.path.exists("database/DogAcademy.db") or refresh:
|
||||||
|
if refresh:
|
||||||
|
print("Обновление базы данных: удаление старых таблиц...")
|
||||||
|
Base.metadata.drop_all(bind=engine) # Удалить все таблицы
|
||||||
|
|
||||||
|
print("Создание базы данных и таблиц...")
|
||||||
|
Base.metadata.create_all(bind=engine) # Создать таблицы заново
|
||||||
else:
|
else:
|
||||||
print("База данных уже существует.")
|
print("База данных уже существует. Обновление не требуется.")
|
||||||
|
|
||||||
|
# Инициализация сессии при запуске
|
||||||
|
current_session = get_session()
|
||||||
|
|
||||||
def get_session():
|
def get_session():
|
||||||
"""Возвращает сессию для работы с базой данных."""
|
"""Возвращает сессию для работы с базой данных."""
|
||||||
return Session()
|
return Session()
|
||||||
|
|
||||||
|
def close_sessions():
|
||||||
|
"""Закрытие всех сессий перед выходом из программы."""
|
||||||
|
if current_session:
|
||||||
|
print("Закрытие сессии...")
|
||||||
|
current_session.close()
|
||||||
|
else:
|
||||||
|
print("Нет активной сессии для закрытия.")
|
||||||
94
database/info/Dogs_table.py
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
|
from database.db_session import get_session
|
||||||
|
from database.models import Dogs
|
||||||
|
|
||||||
|
DOG_CHARACTERS = {
|
||||||
|
"Chihuahua": {
|
||||||
|
"characteristics": "Скорость: 8, Выносливость: 5, Умение: Быстрое уклонение.",
|
||||||
|
"behavior": "Энергичный, часто лайливый.",
|
||||||
|
"care_info": "Нуждается в регулярной чистке зубов и когтей.",
|
||||||
|
"admin_comments": "Идеален для активных владельцев."
|
||||||
|
},
|
||||||
|
"Corgi": {
|
||||||
|
"characteristics": "Скорость: 6, Выносливость: 7, Умение: Дополнительный прыжок.",
|
||||||
|
"behavior": "Дружелюбный, легко обучаемый.",
|
||||||
|
"care_info": "Важно контролировать вес из-за коротких лап.",
|
||||||
|
"admin_comments": "Подходит для семей с детьми."
|
||||||
|
},
|
||||||
|
"Golden Retriever": {
|
||||||
|
"characteristics": "Скорость: 7, Выносливость: 8, Умение: Увеличенные очки за правильные ответы.",
|
||||||
|
"behavior": "Очень умный и добрый.",
|
||||||
|
"care_info": "Требует регулярной чистки шерсти.",
|
||||||
|
"admin_comments": "Идеален для владельцев, ищущих верного друга."
|
||||||
|
},
|
||||||
|
"Husky": {
|
||||||
|
"characteristics": "Скорость: 9, Выносливость: 6, Умение: Ускорение.",
|
||||||
|
"behavior": "Независимый, требует много активности.",
|
||||||
|
"care_info": "Плохо переносит жару, требует частых прогулок.",
|
||||||
|
"admin_comments": "Для опытных владельцев."
|
||||||
|
},
|
||||||
|
"Pomeranian": {
|
||||||
|
"characteristics": "Скорость: 7, Выносливость: 4, Умение: Уменьшение штрафа за ошибки.",
|
||||||
|
"behavior": "Веселый, преданный.",
|
||||||
|
"care_info": "Шерсть требует ежедневного ухода.",
|
||||||
|
"admin_comments": "Идеален для жизни в квартире."
|
||||||
|
},
|
||||||
|
"Pug": {
|
||||||
|
"characteristics": "Скорость: 5, Выносливость: 9, Умение: Сохраняет здоровье при столкновениях.",
|
||||||
|
"behavior": "Ласковый, склонен к перееданию.",
|
||||||
|
"care_info": "Внимание к дыханию и физической активности.",
|
||||||
|
"admin_comments": "Для спокойного образа жизни."
|
||||||
|
},
|
||||||
|
"Yorkshire Terrier": {
|
||||||
|
"characteristics": "Скорость: 6, Выносливость: 5, Умение: Быстрое восстановление характеристик.",
|
||||||
|
"behavior": "Компактный, умный.",
|
||||||
|
"care_info": "Требует профессиональной стрижки.",
|
||||||
|
"admin_comments": "Подходит для маленьких пространств."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def populate_dogs():
|
||||||
|
"""
|
||||||
|
Заполнение таблицы Dogs предустановленными данными.
|
||||||
|
"""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
logging.info("Начинается заполнение таблицы Dogs.")
|
||||||
|
for breed, data in DOG_CHARACTERS.items():
|
||||||
|
existing_dog = session.query(Dogs).filter_by(breed=breed).first()
|
||||||
|
if not existing_dog:
|
||||||
|
dog = Dogs(
|
||||||
|
breed=breed,
|
||||||
|
characteristics=data['characteristics'],
|
||||||
|
behavior=data['behavior'],
|
||||||
|
care_info=data['care_info'],
|
||||||
|
admin_comments=data['admin_comments']
|
||||||
|
)
|
||||||
|
session.add(dog)
|
||||||
|
session.commit()
|
||||||
|
logging.info("Таблица Dogs успешно заполнена.")
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
logging.error(f"Ошибка при заполнении Dogs: {e}")
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_dogs():
|
||||||
|
"""
|
||||||
|
Получение списка всех пород собак из базы данных.
|
||||||
|
|
||||||
|
:return: Список объектов Dogs.
|
||||||
|
"""
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
dogs = session.query(Dogs).all()
|
||||||
|
return dogs
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
logging.error(f"Ошибка при получении списка собак: {e}")
|
||||||
|
return []
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
61
database/info/GameSessions_table.py
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import logging
|
||||||
|
from database.db_events import get_user_progress
|
||||||
|
from database.db_session import get_session
|
||||||
|
from database.models import GameSession
|
||||||
|
|
||||||
|
|
||||||
|
def save_game_session(user_id, level, score, duration, steps, health, hunger, sleepiness):
|
||||||
|
"""Сохранение игрового прогресса с обновлением существующей записи."""
|
||||||
|
session = get_session() # Получаем сессию для работы с базой данных
|
||||||
|
try:
|
||||||
|
# Проверяем, существует ли уже запись для данного пользователя и уровня
|
||||||
|
existing_session = session.query(GameSession).filter_by(user_id=user_id, level=level).first()
|
||||||
|
if existing_session:
|
||||||
|
logging.info(f"Обновление прогресса для user_id={user_id}, level={level}.")
|
||||||
|
existing_session.score = score
|
||||||
|
existing_session.duration = duration
|
||||||
|
existing_session.steps = steps
|
||||||
|
existing_session.health = health
|
||||||
|
existing_session.hunger = hunger
|
||||||
|
existing_session.sleepiness = sleepiness
|
||||||
|
else:
|
||||||
|
# Если записи нет, создаем новую
|
||||||
|
new_session = GameSession(
|
||||||
|
user_id=user_id,
|
||||||
|
level=level,
|
||||||
|
score=score,
|
||||||
|
duration=duration,
|
||||||
|
steps=steps,
|
||||||
|
health=health,
|
||||||
|
hunger=hunger,
|
||||||
|
sleepiness=sleepiness
|
||||||
|
)
|
||||||
|
session.add(new_session) # Добавляем в сессию
|
||||||
|
session.commit() # Сохраняем изменения в базе данных
|
||||||
|
logging.info(f"Прогресс успешно сохранён: user_id={user_id}, level={level}, score={score}")
|
||||||
|
except Exception as e:
|
||||||
|
session.rollback() # Откатываем изменения в случае ошибки
|
||||||
|
logging.error(f"Ошибка при сохранении прогресса: {e}")
|
||||||
|
finally:
|
||||||
|
session.close() # Закрываем сессию
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def print_user_progress(user_id):
|
||||||
|
"""
|
||||||
|
Печать прогресса пользователя из таблицы GameSessions.
|
||||||
|
|
||||||
|
:param user_id: ID пользователя
|
||||||
|
"""
|
||||||
|
if not user_id:
|
||||||
|
logging.error("user_id отсутствует. Невозможно получить прогресс.")
|
||||||
|
return
|
||||||
|
|
||||||
|
progress = get_user_progress(user_id)
|
||||||
|
if not progress:
|
||||||
|
print(f"У пользователя с ID {user_id} нет сохраненного прогресса.")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"Прогресс пользователя (user_id={user_id}):")
|
||||||
|
for session in progress:
|
||||||
|
print(f"- Уровень: {session.level}, Очки: {session.score}, Время: {session.duration} сек")
|
||||||
99
database/info/Questions_table.py
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
from database.db_session import get_session
|
||||||
|
from database.models import Dogs, Questions
|
||||||
|
|
||||||
|
DOG_QUESTIONS = {
|
||||||
|
"Chihuahua": [
|
||||||
|
{
|
||||||
|
"question_text": "Почему у Чихуахуа часто возникают проблемы с зубами?",
|
||||||
|
"helpful_info": "Миниатюрный размер приводит к скоплению налета и зубных отложений.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question_text": "Какая активность лучше всего подходит для Чихуахуа?",
|
||||||
|
"helpful_info": "Легкие прогулки и домашние игры.",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Corgi": [
|
||||||
|
{
|
||||||
|
"question_text": "Почему важно контролировать вес Корги?",
|
||||||
|
"helpful_info": "Избыточный вес может негативно повлиять на суставы.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question_text": "Как можно поддерживать здоровье суставов у Корги?",
|
||||||
|
"helpful_info": "Обеспечьте умеренную активность и сбалансированное питание.",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Golden Retriever": [
|
||||||
|
{
|
||||||
|
"question_text": "Почему важно регулярно вычесывать шерсть Голден Ретривера?",
|
||||||
|
"helpful_info": "Это предотвращает образование колтунов.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question_text": "Какое питание подходит для Голден Ретриверов?",
|
||||||
|
"helpful_info": "Сбалансированное питание с учетом активности и возраста.",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Husky": [
|
||||||
|
{
|
||||||
|
"question_text": "Какой климат подходит для Хаски?",
|
||||||
|
"helpful_info": "Они комфортнее чувствуют себя в холодном климате.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question_text": "Почему Хаски требуют много физической активности?",
|
||||||
|
"helpful_info": "Эта порода обладает высокой энергией и выносливостью.",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Pomeranian": [
|
||||||
|
{
|
||||||
|
"question_text": "Как правильно ухаживать за шерстью Померанского шпица?",
|
||||||
|
"helpful_info": "Ежедневно расчесывать шерсть, чтобы избежать колтунов.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question_text": "Почему важно следить за зубами Померанского шпица?",
|
||||||
|
"helpful_info": "Они склонны к зубному налету, что может привести к проблемам.",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Pug": [
|
||||||
|
{
|
||||||
|
"question_text": "Почему мопсы склонны к ожирению?",
|
||||||
|
"helpful_info": "Их низкая активность и любовь к еде требуют контроля рациона.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question_text": "Какие проблемы с дыханием могут возникнуть у мопсов?",
|
||||||
|
"helpful_info": "Из-за их плоской морды дыхание может быть затруднено.",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Yorkshire Terrier": [
|
||||||
|
{
|
||||||
|
"question_text": "Как часто нужно стричь шерсть Йоркширского терьера?",
|
||||||
|
"helpful_info": "Примерно раз в 4-6 недель для поддержания аккуратного вида.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question_text": "Как ухаживать за шерстью Йоркширского терьера?",
|
||||||
|
"helpful_info": "Регулярно расчесывать и использовать специальные средства.",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def populate_questions():
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
dogs = {dog.breed: dog.dog_id for dog in session.query(Dogs).all()}
|
||||||
|
for breed, questions in DOG_QUESTIONS.items():
|
||||||
|
dog_id = dogs.get(breed)
|
||||||
|
if not dog_id:
|
||||||
|
print(f"Порода '{breed}' отсутствует.")
|
||||||
|
continue
|
||||||
|
for question_data in questions:
|
||||||
|
question = Questions(
|
||||||
|
dog_id=dog_id,
|
||||||
|
question_text=question_data["question_text"],
|
||||||
|
helpful_info=question_data["helpful_info"]
|
||||||
|
)
|
||||||
|
session.add(question)
|
||||||
|
session.commit()
|
||||||
|
print("Таблица Questions успешно заполнена.")
|
||||||
|
except Exception as e:
|
||||||
|
session.rollback()
|
||||||
|
print(f"Ошибка при заполнении Questions: {e}")
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
0
database/info/__init__.py
Normal file
|
|
@ -1,18 +1,18 @@
|
||||||
from sqlalchemy import Column, Integer, String, ForeignKey, Text
|
from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, UniqueConstraint, Boolean
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
from sqlalchemy.sql import func
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
|
||||||
Base = declarative_base()
|
Base = declarative_base()
|
||||||
|
|
||||||
|
|
||||||
class Auth(Base):
|
class Auth(Base):
|
||||||
__tablename__ = 'auth'
|
__tablename__ = 'auth'
|
||||||
user_id = Column(Integer, primary_key=True)
|
user_id = Column(Integer, primary_key=True)
|
||||||
login = Column(String, unique=True, nullable=False)
|
login = Column(String, unique=True, nullable=False)
|
||||||
password = Column(String, nullable=False)
|
password = Column(String, nullable=False)
|
||||||
|
|
||||||
# Связь с таблицей Users
|
user = relationship("Users", back_populates="auth", cascade="all, delete-orphan", uselist=False)
|
||||||
user = relationship("Users", back_populates="auth", uselist=False)
|
|
||||||
|
|
||||||
|
|
||||||
class Users(Base):
|
class Users(Base):
|
||||||
|
|
@ -26,6 +26,8 @@ class Users(Base):
|
||||||
# Связи
|
# Связи
|
||||||
auth = relationship("Auth", back_populates="user") # Обратная связь с Auth
|
auth = relationship("Auth", back_populates="user") # Обратная связь с Auth
|
||||||
dog = relationship("Dogs", back_populates="users") # Связь с таблицей Dogs
|
dog = relationship("Dogs", back_populates="users") # Связь с таблицей Dogs
|
||||||
|
game_sessions = relationship("GameSession", back_populates="user") # Связь с таблицей GameSession
|
||||||
|
notifications = relationship("Notifications", back_populates="user") # Связь с уведомлениями
|
||||||
|
|
||||||
|
|
||||||
class Dogs(Base):
|
class Dogs(Base):
|
||||||
|
|
@ -50,6 +52,40 @@ class Questions(Base):
|
||||||
question_text = Column(Text, nullable=False)
|
question_text = Column(Text, nullable=False)
|
||||||
image_url = Column(String)
|
image_url = Column(String)
|
||||||
helpful_info = Column(Text)
|
helpful_info = Column(Text)
|
||||||
|
incorrect_attempts = Column(Integer, default=0)
|
||||||
|
|
||||||
# Связь с таблицей Dogs
|
# Связь с таблицей Dogs
|
||||||
dog = relationship("Dogs", back_populates="questions")
|
dog = relationship("Dogs", back_populates="questions")
|
||||||
|
|
||||||
|
|
||||||
|
class GameSession(Base):
|
||||||
|
__tablename__ = 'game_sessions'
|
||||||
|
__table_args__ = (
|
||||||
|
UniqueConstraint('user_id', 'level', name='uix_user_level'),
|
||||||
|
)
|
||||||
|
session_id = Column(Integer, primary_key=True)
|
||||||
|
user_id = Column(Integer, ForeignKey('users.user_id'))
|
||||||
|
level = Column(Integer, nullable=False)
|
||||||
|
score = Column(Integer, default=0)
|
||||||
|
duration = Column(Integer) # Время игры в секундах
|
||||||
|
steps = Column(Integer, default=0) # Количество шагов
|
||||||
|
start_time = Column(DateTime, default=func.now())
|
||||||
|
end_time = Column(DateTime, nullable=True)
|
||||||
|
health = Column(Integer, default=100) # Здоровье
|
||||||
|
hunger = Column(Integer, default=0) # Голод
|
||||||
|
sleepiness = Column(Integer, default=0) # Сонливость
|
||||||
|
|
||||||
|
# Связь с таблицей Users
|
||||||
|
user = relationship("Users", back_populates="game_sessions")
|
||||||
|
|
||||||
|
|
||||||
|
class Notifications(Base):
|
||||||
|
__tablename__ = 'notifications'
|
||||||
|
notification_id = Column(Integer, primary_key=True)
|
||||||
|
user_id = Column(Integer, ForeignKey('users.user_id'))
|
||||||
|
message = Column(Text, nullable=False)
|
||||||
|
timestamp = Column(DateTime, default=func.now())
|
||||||
|
is_read = Column(Boolean, default=False) # Булевый тип для read
|
||||||
|
|
||||||
|
# Связь с таблицей Users
|
||||||
|
user = relationship("Users", back_populates="notifications")
|
||||||
BIN
ishodniki/admin_panel.psd
Normal file
BIN
ishodniki/background_game.psd
Normal file
BIN
ishodniki/dogs.psd
Normal file
BIN
ishodniki/user_ui.psd
Normal file
0
logs/database.log
Normal file
919
logs/game.log
Normal file
|
|
@ -0,0 +1,919 @@
|
||||||
|
2024-11-27 04:01:47,401 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:01:47,941 - ERROR - Îøèáêà ïðè âçàèìîäåéñòâèè ñ áàçîé äàííûõ: Entity namespace for "users" has no property "login"
|
||||||
|
2024-11-27 04:05:26,240 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:05:26,795 - ERROR - Îøèáêà ïðè âçàèìîäåéñòâèè ñ áàçîé äàííûõ: (sqlite3.OperationalError) unable to open database file
|
||||||
|
(Background on this error at: https://sqlalche.me/e/20/e3q8)
|
||||||
|
2024-11-27 04:08:19,488 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:08:19,922 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:08:20,024 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:08:20,028 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:08:20,028 - INFO - [generated in 0.00061s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:08:20,030 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:08:20,047 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:20,048 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:20,048 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:20,071 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:20,072 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:20,072 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:08:20,087 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:20,088 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:20,088 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:08:20,101 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:20,102 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:20,102 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:08:20,112 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:20,112 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:20,112 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:08:20,124 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:20,124 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:20,124 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:08:20,139 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:20,139 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:20,139 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:08:21,407 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,408 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,408 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:08:21,408 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:08:21,415 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,415 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,415 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:08:21,432 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,432 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,432 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:08:21,503 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,504 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,504 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:21,518 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,518 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,518 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:08:21,532 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,532 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,532 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:08:21,545 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,546 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,546 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:08:21,555 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,555 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,556 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:08:21,567 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,567 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,567 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:08:21,579 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:21,579 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:21,579 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:08:26,316 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:26,316 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:26,317 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:26,333 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:26,333 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:26,333 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:08:26,347 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:26,347 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:26,348 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:08:26,360 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:26,360 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:26,360 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:08:26,370 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:26,370 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:26,370 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:08:26,381 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:26,381 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:26,381 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:08:26,393 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:26,394 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:26,394 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:08:27,162 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,162 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,162 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:08:27,162 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:08:27,169 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,169 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,169 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:08:27,185 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,185 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,185 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:08:27,256 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,256 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,256 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:27,271 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,271 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,271 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:08:27,285 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,285 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,285 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:08:27,298 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,299 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,299 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:08:27,308 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,309 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,309 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:08:27,320 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,320 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,320 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:08:27,333 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:27,333 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:27,333 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:08:28,177 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:28,177 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:28,177 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:08:32,088 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:32,088 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:32,088 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:32,537 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:32,537 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:32,538 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:32,942 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:32,942 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:32,942 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:33,187 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:33,187 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:33,187 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:33,380 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:33,380 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:33,380 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:33,735 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:33,735 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:33,735 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,247 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,247 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,247 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,277 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,277 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,277 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,308 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,308 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,308 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,339 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,339 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,339 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,370 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,370 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,370 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,402 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,402 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,402 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,448 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,448 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,448 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,479 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,479 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,479 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,510 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,510 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,510 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,541 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,541 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,541 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,571 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,572 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,572 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,603 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,603 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,603 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,634 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,634 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,634 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,664 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,665 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,665 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,711 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,711 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,711 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,742 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,742 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,742 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,772 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,772 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,772 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,803 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,803 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,803 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,833 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,833 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,833 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:34,864 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:34,864 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:34,865 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,170 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,170 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,170 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,672 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,672 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,673 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,704 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,704 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,704 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,750 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,750 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,750 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,781 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,781 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,781 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,813 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,813 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,813 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,843 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,844 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,844 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,875 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,875 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,875 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,907 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,907 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,907 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,937 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,937 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,937 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:35,968 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:35,968 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:35,969 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,015 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,015 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,015 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,046 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,046 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,046 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,077 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,077 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,078 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,109 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,109 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,109 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,140 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,140 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,140 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,170 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,171 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,171 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,201 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,201 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,201 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,496 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,496 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,496 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:36,934 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:36,934 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:36,935 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,444 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,444 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,444 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,475 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,475 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,475 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,506 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,506 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,506 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,537 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,537 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,537 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,569 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,569 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,569 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,614 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,614 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,614 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,645 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,645 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,645 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,676 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,676 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,676 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,707 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,707 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,707 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:37,956 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:37,956 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:37,956 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:38,682 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:38,682 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:38,682 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:39,181 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:39,182 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:39,182 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:39,228 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:39,228 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:39,228 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:39,258 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:39,258 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:39,258 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:39,289 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:39,289 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:39,289 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:39,321 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:39,321 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:39,321 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:39,352 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:39,352 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:39,352 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:39,383 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:08:39,384 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:08:39,384 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:08:41,418 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:09:26,353 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:09:26,804 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:09:26,901 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:09:26,904 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:09:26,904 - INFO - [generated in 0.00028s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:09:26,905 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:09:26,920 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:26,920 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:26,920 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:09:26,942 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:26,942 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:26,943 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:09:26,958 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:26,958 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:26,958 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:09:26,972 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:26,972 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:26,972 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:09:26,984 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:26,985 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:26,985 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:09:26,996 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:26,996 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:26,996 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:09:27,010 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:27,010 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:27,010 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:09:28,434 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,435 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,435 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:09:28,435 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:09:28,442 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,442 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,442 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:09:28,459 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,459 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,459 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:09:28,530 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,530 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,530 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:09:28,545 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,545 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,545 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:09:28,559 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,560 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,560 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:09:28,573 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,573 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,573 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:09:28,583 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,583 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,583 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:09:28,594 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,594 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,594 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:09:28,607 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:09:28,607 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:09:28,607 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:11:03,632 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:11:03,632 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:11:03,632 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:11:26,828 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:11:26,828 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:11:26,828 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:12:26,226 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:12:28,471 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:12:28,899 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:12:28,997 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:12:29,000 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:12:29,000 - INFO - [generated in 0.00029s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:12:29,001 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:12:29,015 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,015 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,015 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:12:29,038 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,038 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,038 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:12:29,053 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,053 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,054 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:12:29,068 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,068 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,068 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:12:29,078 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,078 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,079 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:12:29,090 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,090 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,090 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:12:29,103 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,104 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,104 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:12:29,841 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,841 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,841 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:12:29,841 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:12:29,848 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,849 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,849 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:12:29,865 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,865 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,865 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:12:29,934 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,935 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,935 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:12:29,949 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,950 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,950 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:12:29,965 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,965 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,965 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:12:29,979 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,980 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,980 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:12:29,990 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:29,990 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:29,990 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:12:30,002 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:30,002 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:30,002 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:12:30,016 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:30,016 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:30,016 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:12:30,808 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:30,808 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:30,808 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:12:34,561 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:12:34,561 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:12:34,561 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:17:58,361 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:18:49,054 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:18:49,525 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:18:49,627 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:18:49,629 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:18:49,630 - INFO - [generated in 0.00025s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:18:49,630 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:18:49,647 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:49,647 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:49,647 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:18:49,670 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:49,670 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:49,670 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:18:49,686 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:49,686 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:49,686 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:18:49,701 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:49,701 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:49,701 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:18:49,711 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:49,712 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:49,712 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:18:49,723 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:49,724 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:49,724 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:18:49,737 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:49,737 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:49,738 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:18:50,592 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,593 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,593 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:18:50,593 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:18:50,600 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,600 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,600 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:18:50,617 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,618 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,618 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:18:50,685 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,686 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,686 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:18:50,702 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,702 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,702 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:18:50,720 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,720 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,720 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:18:50,737 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,737 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,737 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:18:50,748 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,748 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,748 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:18:50,761 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,761 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,761 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:18:50,775 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:50,775 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:50,775 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:18:52,809 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:52,810 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:52,810 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:18:56,823 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:18:56,823 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:18:56,823 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:19:14,325 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:20:41,642 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:20:42,172 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:20:42,283 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:20:42,285 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:20:42,285 - INFO - [generated in 0.00028s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:20:42,286 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:20:42,307 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:42,307 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:42,307 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:20:42,330 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:42,331 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:42,331 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:20:42,346 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:42,346 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:42,346 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:20:42,362 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:42,362 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:42,362 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:20:42,373 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:42,373 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:42,373 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:20:42,387 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:42,387 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:42,387 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:20:42,401 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:42,401 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:42,402 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:20:43,204 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,204 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,204 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:20:43,204 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:20:43,211 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,212 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,212 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:20:43,229 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,229 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,229 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:20:43,304 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,304 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,305 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:20:43,320 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,320 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,320 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:20:43,337 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,337 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,337 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:20:43,352 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,353 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,353 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:20:43,363 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,363 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,363 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:20:43,375 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,375 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,375 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:20:43,389 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:20:43,389 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:20:43,389 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:21:16,405 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:16,405 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:16,405 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:21:20,530 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:20,530 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:20,530 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:21:27,458 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:21:39,761 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:21:40,188 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:21:40,294 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:21:40,296 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:21:40,296 - INFO - [generated in 0.00025s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:21:40,297 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:21:40,312 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:40,312 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:40,312 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:21:40,334 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:40,334 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:40,334 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:21:40,350 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:40,350 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:40,350 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:21:40,363 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:40,364 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:40,364 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:21:40,375 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:40,375 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:40,375 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:21:40,387 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:40,387 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:40,387 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:21:40,400 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:40,401 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:40,401 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:21:41,365 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,365 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,365 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:21:41,365 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:21:41,372 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,372 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,372 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:21:41,389 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,390 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,390 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:21:41,463 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,463 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,463 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:21:41,481 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,481 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,482 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:21:41,503 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,504 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,504 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:21:41,525 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,525 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,525 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:21:41,538 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,538 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,538 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:21:41,552 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,552 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,552 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:21:41,568 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:41,569 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:41,569 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:21:44,529 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:44,529 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:44,529 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:21:48,501 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:21:48,501 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:21:48,501 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:21:58,037 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:23:20,095 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:23:20,529 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:23:20,637 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:23:20,639 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:23:20,640 - INFO - [generated in 0.00029s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:23:20,640 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:23:20,655 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:20,655 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:20,655 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:23:20,678 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:20,678 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:20,678 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:23:20,693 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:20,693 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:20,693 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:23:20,707 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:20,707 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:20,707 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:23:20,718 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:20,718 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:20,718 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:23:20,730 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:20,730 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:20,730 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:23:20,743 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:20,743 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:20,743 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:23:21,610 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,610 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,610 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:23:21,610 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:23:21,617 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,618 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,618 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:23:21,634 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,634 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,635 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:23:21,707 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,707 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,707 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:23:21,724 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,724 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,724 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:23:21,745 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,745 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,745 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:23:21,765 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,765 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,765 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:23:21,776 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,777 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,777 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:23:21,790 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,790 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,790 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:23:21,805 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:21,805 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:21,805 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:23:22,532 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:22,532 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:22,532 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:23:26,429 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:23:26,429 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:23:26,429 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:23:31,839 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:26:48,168 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:26:48,266 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:26:48,269 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:26:48,269 - INFO - [generated in 0.00021s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:26:48,269 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:26:48,284 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:26:48,284 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:26:48,284 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:26:48,307 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:26:48,307 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:26:48,307 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:26:48,322 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:26:48,323 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:26:48,323 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:26:48,337 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:26:48,337 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:26:48,337 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:26:48,347 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:26:48,347 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:26:48,347 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:26:48,359 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:26:48,359 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:26:48,359 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:26:48,373 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:26:48,373 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:26:48,373 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:26:56,174 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:28:00,201 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:28:00,689 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:28:00,802 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:28:00,805 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:28:00,805 - INFO - [generated in 0.00029s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:28:00,806 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:28:00,823 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:00,823 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:00,823 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:28:00,848 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:00,848 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:00,849 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:28:00,864 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:00,865 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:00,865 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:28:00,879 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:00,879 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:00,879 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:28:00,890 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:00,890 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:00,890 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:28:00,903 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:00,903 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:00,903 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:28:00,918 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:00,918 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:00,918 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:28:01,704 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,704 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,704 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:28:01,704 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:28:01,712 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,712 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,712 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:28:01,729 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,729 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,729 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:28:01,809 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,809 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,809 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:28:01,828 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,829 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,829 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:28:01,851 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,851 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,852 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:28:01,874 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,874 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,874 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:28:01,887 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,887 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,887 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:28:01,902 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,902 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,902 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:28:01,918 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:01,918 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:01,919 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:28:03,370 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:03,370 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:03,370 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:28:07,271 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:07,271 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:07,272 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:28:11,499 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:28:25,505 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:28:25,929 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:28:26,029 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:28:26,031 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:28:26,031 - INFO - [generated in 0.00023s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:28:26,032 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:28:26,047 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,047 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,047 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:28:26,070 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,070 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,070 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:28:26,087 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,087 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,087 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:28:26,101 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,101 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,102 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:28:26,112 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,113 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,113 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:28:26,126 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,126 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,126 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:28:26,140 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,140 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,140 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:28:26,992 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:26,992 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:26,992 - DEBUG - STREAM b'tEXt' 62 25
|
||||||
|
2024-11-27 04:28:26,993 - DEBUG - STREAM b'IDAT' 99 8192
|
||||||
|
2024-11-27 04:28:26,999 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,000 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,000 - DEBUG - STREAM b'IDAT' 62 29837
|
||||||
|
2024-11-27 04:28:27,016 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,016 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,016 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:28:27,088 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,088 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,088 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:28:27,107 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,107 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,107 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:28:27,129 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,129 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,129 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:28:27,151 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,151 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,151 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:28:27,163 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,163 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,164 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:28:27,177 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,178 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,178 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:28:27,194 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:27,194 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:27,194 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:28:28,409 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:28,409 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:28,409 - DEBUG - STREAM b'IDAT' 62 840969
|
||||||
|
2024-11-27 04:28:32,335 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:28:32,336 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:28:32,336 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:28:38,371 - INFO - ROLLBACK
|
||||||
|
2024-11-27 04:32:09,489 - INFO - Ëîãèðîâàíèå èãðû íà÷àòî.
|
||||||
|
2024-11-27 04:32:09,948 - INFO - Ïîäêëþ÷åíèå ê áàçå äàííûõ óñïåøíî.
|
||||||
|
2024-11-27 04:32:10,049 - INFO - BEGIN (implicit)
|
||||||
|
2024-11-27 04:32:10,052 - INFO - SELECT auth.user_id AS auth_user_id, auth.login AS auth_login, auth.password AS auth_password
|
||||||
|
FROM auth
|
||||||
|
WHERE auth.login = ? AND auth.password = ?
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
2024-11-27 04:32:10,052 - INFO - [generated in 0.00023s] ('lubluNikitu', 'meow123', 1, 0)
|
||||||
|
2024-11-27 04:32:10,053 - INFO - Ïîëüçîâàòåëü íàéäåí: lubluNikitu
|
||||||
|
2024-11-27 04:32:10,068 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:32:10,068 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:32:10,068 - DEBUG - STREAM b'IDAT' 62 333841
|
||||||
|
2024-11-27 04:32:10,091 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:32:10,092 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:32:10,092 - DEBUG - STREAM b'IDAT' 62 259015
|
||||||
|
2024-11-27 04:32:10,107 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:32:10,107 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:32:10,107 - DEBUG - STREAM b'IDAT' 62 220337
|
||||||
|
2024-11-27 04:32:10,121 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:32:10,121 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:32:10,121 - DEBUG - STREAM b'IDAT' 62 177624
|
||||||
|
2024-11-27 04:32:10,131 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:32:10,132 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:32:10,132 - DEBUG - STREAM b'IDAT' 62 232384
|
||||||
|
2024-11-27 04:32:10,143 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:32:10,143 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:32:10,144 - DEBUG - STREAM b'IDAT' 62 261264
|
||||||
|
2024-11-27 04:32:10,157 - DEBUG - STREAM b'IHDR' 16 13
|
||||||
|
2024-11-27 04:32:10,157 - DEBUG - STREAM b'pHYs' 41 9
|
||||||
|
2024-11-27 04:32:10,157 - DEBUG - STREAM b'IDAT' 62 348922
|
||||||
|
2024-11-27 04:32:12,820 - INFO - ROLLBACK
|
||||||
24814
logs/logfile.log
Normal file
|
|
@ -1,2 +0,0 @@
|
||||||
sqlalchemy
|
|
||||||
tk
|
|
||||||
BIN
src/__pycache__/utils.cpython-313.pyc
Normal file
BIN
src/admin_functions/__pycache__/admin_logging.cpython-313.pyc
Normal file
BIN
src/admin_functions/__pycache__/content.cpython-313.pyc
Normal file
BIN
src/admin_functions/__pycache__/knowledge_base.cpython-313.pyc
Normal file
BIN
src/admin_functions/__pycache__/notification.cpython-313.pyc
Normal file
BIN
src/admin_functions/__pycache__/statistics.cpython-313.pyc
Normal file
54
src/admin_functions/admin_logging.py
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
import csv
|
||||||
|
from src.utils import clear_frame
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
BACKGROUND_COLOR = "#403d49"
|
||||||
|
TEXT_COLOR = "#b2acc0"
|
||||||
|
HEADER_COLOR = "#2f2b38"
|
||||||
|
BUTTON_COLOR = "#444444"
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
filename="logs/logfile.log",
|
||||||
|
level=logging.INFO,
|
||||||
|
format="%(asctime)s - %(message)s",
|
||||||
|
datefmt="%Y-%m-%d %H:%M:%S"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def log_action(action, user):
|
||||||
|
logging.info(f"{action} - Пользователь: {user}")
|
||||||
|
|
||||||
|
|
||||||
|
def show_logs(frame):
|
||||||
|
"""Отображение логов действий пользователей в тёмной теме."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Логи действий", font=("Comic Sans MS", 16), bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
|
||||||
|
# Настройка таблицы с логами
|
||||||
|
table = ttk.Treeview(frame, columns=("Время", "Действие", "Пользователь"), show="headings", style="Dark.Treeview")
|
||||||
|
table.heading("Время", text="Время")
|
||||||
|
table.heading("Действие", text="Действие")
|
||||||
|
table.heading("Пользователь", text="Пользователь")
|
||||||
|
table.pack(fill="both", expand=True)
|
||||||
|
|
||||||
|
# Добавление логов для примера
|
||||||
|
table.insert("", "end", values=("2024-11-19 12:30", "Добавление вопроса", "admin"))
|
||||||
|
table.insert("", "end", values=("2024-11-19 13:00", "Удаление пользователя", "moderator"))
|
||||||
|
|
||||||
|
# Применение стиля к таблице
|
||||||
|
style = ttk.Style()
|
||||||
|
style.configure("Dark.Treeview", background=BACKGROUND_COLOR, foreground=TEXT_COLOR, fieldbackground=BACKGROUND_COLOR)
|
||||||
|
style.configure("Dark.Treeview.Heading", background=HEADER_COLOR, foreground=TEXT_COLOR)
|
||||||
|
|
||||||
|
def export_logs():
|
||||||
|
data = [
|
||||||
|
("2024-11-19 12:30", "Добавление вопроса", "admin"),
|
||||||
|
("2024-11-19 13:00", "Удаление пользователя", "moderator"),
|
||||||
|
]
|
||||||
|
with open("logs.csv", "w", newline="", encoding="utf-8") as file:
|
||||||
|
writer = csv.writer(file)
|
||||||
|
writer.writerow(["Время", "Действие", "Пользователь"])
|
||||||
|
writer.writerows(data)
|
||||||
|
print("Логи успешно экспортированы в logs.csv")
|
||||||
17
src/admin_functions/content.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from src.utils import clear_frame
|
||||||
|
|
||||||
|
def manage_levels(frame):
|
||||||
|
"""Создание и настройка уровней."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Создание и настройка уровней", font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
# Добавить интерфейс для добавления уровней
|
||||||
|
|
||||||
|
|
||||||
|
def manage_dog_params(frame):
|
||||||
|
"""Настройка параметров собаки."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Настройка параметров собаки", font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
# Добавить поля для параметров, например, здоровье, голод, сонливость
|
||||||
51
src/admin_functions/knowledge_base.py
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
from tkinter import ttk
|
||||||
|
import tkinter as tk
|
||||||
|
from src.utils import clear_frame
|
||||||
|
|
||||||
|
def add_info(frame):
|
||||||
|
"""Добавление информации о породах собак."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Добавление информации", font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
# Реализовать интерфейс для добавления данных
|
||||||
|
|
||||||
|
|
||||||
|
def edit_records(frame):
|
||||||
|
"""Редактирование записей в базе знаний."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Редактирование записей", font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
# Реализовать интерфейс для редактирования записей
|
||||||
|
|
||||||
|
|
||||||
|
def delete_records(frame):
|
||||||
|
"""Удаление записей из базы знаний."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Удаление записей", font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
# Реализовать интерфейс для удаления данных
|
||||||
|
|
||||||
|
|
||||||
|
def view_knowledge_base(frame):
|
||||||
|
"""Просмотр базы знаний."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="База знаний", font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
table = ttk.Treeview(frame, columns=("Порода", "Описание"), show="headings")
|
||||||
|
table.heading("Порода", text="Порода")
|
||||||
|
table.heading("Описание", text="Описание")
|
||||||
|
table.pack(fill="both", expand=True)
|
||||||
|
|
||||||
|
# Пример данных
|
||||||
|
table.insert("", "end", values=("Лабрадор", "Дружелюбная порода"))
|
||||||
|
table.insert("", "end", values=("Доберман", "Отличный сторож"))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_questions(frame):
|
||||||
|
print("Я по приколу вызвался")
|
||||||
|
"""Генерация вопросов на основе текстов."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Генерация вопросов", font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
# Реализовать генерацию вопросов
|
||||||
|
|
||||||
17
src/admin_functions/notification.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class Notification:
|
||||||
|
def __init__(self, parent, message, timestamp):
|
||||||
|
self.frame = tk.Frame(parent, bg="#2f2b38", pady=5)
|
||||||
|
self.frame.pack(fill="x", pady=5)
|
||||||
|
|
||||||
|
self.message_label = tk.Label(self.frame, text=message, bg="#2f2b38", fg="#b2acc0", font=("Comic Sans MS", 12))
|
||||||
|
self.message_label.pack(side="left", padx=10)
|
||||||
|
|
||||||
|
self.timestamp_label = tk.Label(self.frame, text=self.format_timestamp(timestamp), bg="#2f2b38", fg="#b2acc0", font=("Comic Sans MS", 10))
|
||||||
|
self.timestamp_label.pack(side="right", padx=10)
|
||||||
|
|
||||||
|
def format_timestamp(self, timestamp):
|
||||||
|
"""Форматирование метки времени."""
|
||||||
|
return datetime.strptime(str(timestamp), "%Y-%m-%d %H:%M:%S").strftime("%d-%m-%Y %H:%M:%S")
|
||||||
0
src/admin_functions/security.py
Normal file
98
src/admin_functions/statistics.py
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||||
|
from src.utils import clear_frame
|
||||||
|
from database.db_session import get_session
|
||||||
|
from sqlalchemy.sql import func
|
||||||
|
from database.models import Users, GameSession, Questions # Пример моделей
|
||||||
|
|
||||||
|
def show_statistics(frame):
|
||||||
|
"""Отображение статистики."""
|
||||||
|
clear_frame(frame)
|
||||||
|
tk.Label(frame, text="Статистика", font=("Comic Sans MS", 16), bg="#403d49", fg="#b2acc0").pack(pady=10)
|
||||||
|
|
||||||
|
# Таблица с общей статистикой
|
||||||
|
table = ttk.Treeview(frame, columns=("Metric", "Value"), show="headings", height=5)
|
||||||
|
table.heading("Metric", text="Параметр")
|
||||||
|
table.heading("Value", text="Значение")
|
||||||
|
table.pack(pady=10, padx=20, fill="x", expand=True)
|
||||||
|
|
||||||
|
# Получение данных для таблицы
|
||||||
|
stats = gather_statistics()
|
||||||
|
for metric, value in stats.items():
|
||||||
|
table.insert("", tk.END, values=(metric, value))
|
||||||
|
|
||||||
|
# График активности пользователей
|
||||||
|
tk.Label(frame, text="Активность пользователей", font=("Comic Sans MS", 14), bg="#403d49", fg="#b2acc0").pack(pady=10)
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(figsize=(6, 4))
|
||||||
|
time_labels, activity_values = get_user_activity()
|
||||||
|
ax.plot(time_labels, activity_values, marker="o")
|
||||||
|
ax.set_title("Активность пользователей по времени")
|
||||||
|
ax.set_xlabel("Время")
|
||||||
|
ax.set_ylabel("Количество действий")
|
||||||
|
ax.grid()
|
||||||
|
|
||||||
|
canvas = FigureCanvasTkAgg(fig, master=frame)
|
||||||
|
canvas.get_tk_widget().pack(fill="both", expand=True)
|
||||||
|
canvas.draw()
|
||||||
|
|
||||||
|
def gather_statistics():
|
||||||
|
"""Собирает основные метрики для таблицы статистики."""
|
||||||
|
session = get_session()
|
||||||
|
|
||||||
|
# Количество зарегистрированных пользователей
|
||||||
|
user_count = session.query(Users).count()
|
||||||
|
|
||||||
|
# Популярные уровни
|
||||||
|
level_data = session.query(GameSession.level, func.count(GameSession.session_id)).group_by(GameSession.level).all()
|
||||||
|
popular_levels = sorted(level_data, key=lambda x: x[1], reverse=True)[:3]
|
||||||
|
|
||||||
|
# Трудные вопросы
|
||||||
|
question_data = session.query(Questions.question_text, Questions.incorrect_attempts).order_by(Questions.incorrect_attempts.desc()).all()
|
||||||
|
hardest_questions = question_data[:3]
|
||||||
|
|
||||||
|
# Средняя продолжительность игры
|
||||||
|
avg_duration = session.query(func.avg(GameSession.duration)).scalar() or 0
|
||||||
|
|
||||||
|
# Состояние базы данных
|
||||||
|
db_size = get_database_size()
|
||||||
|
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"Количество пользователей": user_count,
|
||||||
|
"Популярные уровни": ", ".join([f"Уровень {lvl} ({cnt} раз)" for lvl, cnt in popular_levels]),
|
||||||
|
"Трудные вопросы": ", ".join([f"'{text}' ({cnt} ошибок)" for text, cnt in hardest_questions]),
|
||||||
|
"Средняя продолжительность игры": f"{avg_duration:.2f} секунд",
|
||||||
|
"Объем базы данных": f"{db_size} КБ"
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_user_activity():
|
||||||
|
"""Генерирует данные для графика активности пользователей."""
|
||||||
|
session = get_session()
|
||||||
|
activity_data = session.query(GameSession.start_time).all()
|
||||||
|
|
||||||
|
activity_by_hour = {}
|
||||||
|
for time in activity_data:
|
||||||
|
hour = time.start_time.hour
|
||||||
|
activity_by_hour[hour] = activity_by_hour.get(hour, 0) + 1
|
||||||
|
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
if not activity_by_hour:
|
||||||
|
return ["Нет данных"], [0]
|
||||||
|
|
||||||
|
hours = sorted(activity_by_hour.keys())
|
||||||
|
activity = [activity_by_hour[hour] for hour in hours]
|
||||||
|
hours = [f"{hour}:00" for hour in hours]
|
||||||
|
return hours, activity
|
||||||
|
|
||||||
|
def get_database_size():
|
||||||
|
"""Возвращает размер базы данных в КБ."""
|
||||||
|
import os
|
||||||
|
db_path = "database/db.sqlite"
|
||||||
|
if os.path.exists(db_path):
|
||||||
|
return round(os.path.getsize(db_path) / 1024, 2)
|
||||||
|
return 0
|
||||||
60
src/auth.py
|
|
@ -1,19 +1,49 @@
|
||||||
from database.db_session import session
|
import logging
|
||||||
from database.models import Auth, Users
|
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
from database.db_session import get_session
|
||||||
|
from database.models import Auth, Users, GameSession
|
||||||
|
|
||||||
|
|
||||||
def register_user(login, password, username):
|
def register_user(login, password, username):
|
||||||
if session.query(Auth).filter_by(login=login).first():
|
"""Регистрация нового пользователя."""
|
||||||
return False, "Логин уже используется."
|
session = get_session()
|
||||||
new_auth = Auth(login=login, password=password)
|
try:
|
||||||
session.add(new_auth)
|
if session.query(Auth).filter_by(login=login).first():
|
||||||
session.commit()
|
return False, "Логин уже используется."
|
||||||
new_user = Users(user_id=new_auth.user_id, username=username)
|
|
||||||
session.add(new_user)
|
# Создаем новую запись в Auth
|
||||||
session.commit()
|
new_auth = Auth(login=login, password=password)
|
||||||
return True, "Регистрация успешна."
|
session.add(new_auth)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
# Создаем запись в Users
|
||||||
|
new_user = Users(user_id=new_auth.user_id, username=username)
|
||||||
|
session.add(new_user)
|
||||||
|
|
||||||
|
# Создаем запись в GameSession
|
||||||
|
new_game_session = GameSession(user_id=new_user.user_id, level=1)
|
||||||
|
session.add(new_game_session)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
return True, "Регистрация успешна."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
session.rollback()
|
||||||
|
logging.error(f"Ошибка при регистрации: {e}")
|
||||||
|
return False, "Произошла ошибка при регистрации."
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
def login_user(login, password):
|
def login_user(login, password):
|
||||||
user = session.query(Auth).filter_by(login=login, password=password).first()
|
"""Авторизация пользователя."""
|
||||||
if user:
|
session = get_session()
|
||||||
return True, user.user_id
|
try:
|
||||||
return False, "Неверный логин или пароль."
|
auth = session.query(Auth).filter_by(login=login, password=password).first()
|
||||||
|
if auth:
|
||||||
|
return True, auth.user_id
|
||||||
|
return False, "Неверный логин или пароль."
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
return False, f"Ошибка авторизации: {e}"
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
|
||||||
32
src/main.py
|
|
@ -1,16 +1,32 @@
|
||||||
from tkinter import Tk
|
import sys
|
||||||
from src.ui.auth_ui import DogAcademyApp # Изменил на правильный путь
|
import os
|
||||||
from database.db_session import init_db
|
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
|
||||||
|
from tkinter import Tk, messagebox
|
||||||
|
from src.ui.auth_ui import DogAcademyApp # Путь к приложению
|
||||||
|
from database.db_session import init_db, close_sessions # Функция для закрытия сессий
|
||||||
|
|
||||||
|
def on_close():
|
||||||
|
"""Обработчик закрытия окна."""
|
||||||
|
if messagebox.askokcancel("Выход", "Вы действительно хотите выйти?"):
|
||||||
|
print("Закрытие игры...")
|
||||||
|
close_sessions() # Закрытие всех сессий перед выходом
|
||||||
|
root.quit() # Завершаем главный цикл приложения
|
||||||
|
root.destroy() # Закрытие окна
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Основной запуск приложения."""
|
"""Основной запуск приложения."""
|
||||||
# Инициализируем базу данных
|
global root
|
||||||
|
# Инициализация базы данных
|
||||||
init_db()
|
init_db()
|
||||||
|
|
||||||
# Запускаем графический интерфейс
|
# Создаем экземпляр приложения
|
||||||
root = Tk()
|
|
||||||
app = DogAcademyApp(root)
|
app = DogAcademyApp(root)
|
||||||
root.mainloop()
|
root.protocol("WM_DELETE_WINDOW", on_close) # Перехват события закрытия окна
|
||||||
|
root.mainloop() # Запуск основного цикла обработки событий
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
root = Tk() # Создание корневого окна
|
||||||
|
root.overrideredirect(True) # Убираем рамки окна
|
||||||
|
root.geometry("1920x1080") # Устанавливаем размер окна
|
||||||
|
main()
|
||||||
39
src/tests/database_test.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
from database.db_session import get_session, init_db
|
||||||
|
from database.info.Dogs_table import populate_dogs
|
||||||
|
from database.info.Questions_table import populate_questions
|
||||||
|
from database.models import Dogs, Questions
|
||||||
|
|
||||||
|
|
||||||
|
def test_data_integrity():
|
||||||
|
session = get_session()
|
||||||
|
try:
|
||||||
|
# Проверяем, есть ли собаки
|
||||||
|
dogs = session.query(Dogs).all()
|
||||||
|
assert len(dogs) > 0, "Таблица Dogs пуста!"
|
||||||
|
|
||||||
|
# Проверяем, есть ли вопросы
|
||||||
|
questions = session.query(Questions).all()
|
||||||
|
assert len(questions) > 0, "Таблица Questions пуста!"
|
||||||
|
|
||||||
|
# Проверяем связь вопросов с породами
|
||||||
|
for question in questions:
|
||||||
|
assert question.dog_id is not None, f"У вопроса {question.question_id} отсутствует dog_id"
|
||||||
|
dog = session.query(Dogs).filter_by(dog_id=question.dog_id).first()
|
||||||
|
assert dog is not None, f"Ссылка на несуществующую собаку в вопросе {question.question_id}"
|
||||||
|
|
||||||
|
print("Все тесты успешно пройдены.")
|
||||||
|
except AssertionError as e:
|
||||||
|
print(f"Ошибка теста: {e}")
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Инициализируем базу данных (пересоздаём таблицы для чистого теста)
|
||||||
|
init_db(refresh=True)
|
||||||
|
|
||||||
|
# Заполняем таблицы
|
||||||
|
populate_dogs()
|
||||||
|
populate_questions()
|
||||||
|
|
||||||
|
# Запускаем тесты
|
||||||
|
test_data_integrity()
|
||||||
67
src/tests/game_test.py
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from src.ui.user_ui.main_menu import UserApp
|
||||||
|
from database.db_session import create_session
|
||||||
|
from database.models import Auth, Users
|
||||||
|
import logging
|
||||||
|
from config import DATABASE_URL
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_interface():
|
||||||
|
"""Тестовый запуск пользовательского интерфейса с обходом авторизации."""
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
# Проверка пути к базе данных
|
||||||
|
engine = create_engine(DATABASE_URL)
|
||||||
|
try:
|
||||||
|
with engine.connect() as connection:
|
||||||
|
logging.info("Подключение к базе данных успешно.")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Не удалось подключиться к базе данных: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Настройка окна
|
||||||
|
root = tk.Tk()
|
||||||
|
root.geometry("1920x1080")
|
||||||
|
root.title("Dog Academy Game - Тестовый режим")
|
||||||
|
|
||||||
|
# Данные для авторизации
|
||||||
|
test_login = "lubluNikitu"
|
||||||
|
test_password = "meow123"
|
||||||
|
|
||||||
|
# Проверка авторизации или создание пользователя напрямую
|
||||||
|
try:
|
||||||
|
session = create_session()
|
||||||
|
|
||||||
|
# Проверяем, существует ли пользователь в таблице Auth
|
||||||
|
user_auth = session.query(Auth).filter_by(login=test_login, password=test_password).first()
|
||||||
|
|
||||||
|
if not user_auth:
|
||||||
|
logging.warning("Пользователь не найден или пароль неверный. Создаём тестового пользователя.")
|
||||||
|
# Создаём нового пользователя в таблице Auth и Users
|
||||||
|
new_user_auth = Auth(login=test_login, password=test_password)
|
||||||
|
session.add(new_user_auth)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
new_user = Users(username="Test User", auth=new_user_auth)
|
||||||
|
session.add(new_user)
|
||||||
|
session.commit()
|
||||||
|
user_id = new_user.user_id
|
||||||
|
else:
|
||||||
|
# Получаем user_id пользователя из таблицы Users, связанного с Auth
|
||||||
|
user_id = user_auth.user_id
|
||||||
|
logging.info(f"Пользователь найден: {test_login}")
|
||||||
|
|
||||||
|
# Запуск главного меню для пользователя
|
||||||
|
app = UserApp(root, user_id=user_id)
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Ошибка при взаимодействии с базой данных: {e}")
|
||||||
|
session.rollback()
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_user_interface()
|
||||||
|
|
@ -1,59 +1,750 @@
|
||||||
# admin_ui.py
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from config import BACKGROUND_COLOR, PRIMARY_COLOR, BUTTON_COLOR, BUTTON_TEXT_COLOR, FONT
|
from tkinter import messagebox, ttk
|
||||||
|
from PIL import Image, ImageTk
|
||||||
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
|
|
||||||
|
from config import SETTINGS_IMG
|
||||||
|
from database.db_session import get_session
|
||||||
|
from database.models import Dogs, Questions, Users
|
||||||
|
from src.admin_functions import admin_logging, statistics
|
||||||
|
from src.utils import clear_frame, feature_in_development_admin # Импортируем общую функцию для очистки фрейма
|
||||||
|
from database.db_events import check_user, get_all_users, get_all_questions, get_all_dogs, delete_dog, update_dog_info, \
|
||||||
|
add_question_to_db, add_user_to_db, add_dog_to_db, delete_question, delete_user
|
||||||
|
|
||||||
|
# Конфигурация цветов из config.py
|
||||||
|
BACKGROUND_COLOR = "#403d49"
|
||||||
|
TOP_BAR_COLOR = "#383441"
|
||||||
|
TEXT_COLOR = "#b2acc0"
|
||||||
|
BUTTON_COLOR = "#403d49"
|
||||||
|
MENU_COLOR = "#2f2b38"
|
||||||
|
MENU_OPACITY = 0.9 # Прозрачность меню
|
||||||
|
|
||||||
class AdminApp:
|
class AdminApp:
|
||||||
def __init__(self, root):
|
def __init__(self, root):
|
||||||
self.root = root
|
self.root = root
|
||||||
self.show_admin_dashboard()
|
self.root.title("Админ-Панель")
|
||||||
|
self.root.geometry("1920x1080")
|
||||||
|
self.root.config(bg=BACKGROUND_COLOR)
|
||||||
|
|
||||||
def show_admin_dashboard(self):
|
# Верхняя панель
|
||||||
"""Показать интерфейс администратора."""
|
self.top_bar = tk.Frame(self.root, bg=TOP_BAR_COLOR, height=60)
|
||||||
self.clear_frame()
|
self.top_bar.pack(side="top", fill="x")
|
||||||
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
|
||||||
self.current_frame.pack(expand=True)
|
|
||||||
|
|
||||||
# Заголовок
|
# Кнопка настроек
|
||||||
title = tk.Label(
|
settings_img = Image.open(SETTINGS_IMG)
|
||||||
self.current_frame,
|
settings_img = settings_img.resize((40, 40), Image.Resampling.LANCZOS)
|
||||||
text="Админ-Панель",
|
settings_icon = ImageTk.PhotoImage(settings_img)
|
||||||
|
|
||||||
|
self.settings_button = tk.Button(
|
||||||
|
self.top_bar,
|
||||||
|
image=settings_icon,
|
||||||
|
bg=TOP_BAR_COLOR,
|
||||||
|
activebackground=TOP_BAR_COLOR,
|
||||||
|
bd=0
|
||||||
|
)
|
||||||
|
self.settings_button.image = settings_icon # Сохраняем ссылку на изображение
|
||||||
|
self.settings_button.pack(side="left", padx=10, pady=10)
|
||||||
|
|
||||||
|
# Кнопки навигации
|
||||||
|
self.create_nav_button("Логирование", lambda: admin_logging.show_logs(self.main_frame))
|
||||||
|
self.create_nav_button("Статистика", lambda: statistics.show_statistics(self.main_frame))
|
||||||
|
self.create_nav_button("Уведомления", lambda: self.show_notifications(self.main_frame))
|
||||||
|
self.create_nav_button("Безопасность", lambda: self.show_security(self.main_frame))
|
||||||
|
self.create_nav_button("Открыть сессию пользователя", self.open_user_session)
|
||||||
|
|
||||||
|
# Бургер-меню
|
||||||
|
self.menu_button = tk.Button(
|
||||||
|
self.top_bar,
|
||||||
|
text="☰ Меню",
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 14),
|
||||||
|
activebackground=BUTTON_COLOR,
|
||||||
|
activeforeground=TEXT_COLOR,
|
||||||
|
bd=0,
|
||||||
|
command=self.toggle_menu
|
||||||
|
)
|
||||||
|
self.menu_button.pack(side="right", padx=10, pady=10)
|
||||||
|
|
||||||
|
# Основное окно
|
||||||
|
self.main_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
||||||
|
self.main_frame.pack(fill="both", expand=True)
|
||||||
|
|
||||||
|
# Бургер-меню (скрытое по умолчанию)
|
||||||
|
self.menu_frame = tk.Frame(self.root, bg=MENU_COLOR, width=300)
|
||||||
|
self.menu_frame.place(x=1620, y=60, width=300, height=1020)
|
||||||
|
self.menu_frame.lower()
|
||||||
|
self.menu_visible = False
|
||||||
|
|
||||||
|
def toggle_menu(self):
|
||||||
|
"""Показ или скрытие меню."""
|
||||||
|
if self.menu_visible:
|
||||||
|
self.menu_frame.lower()
|
||||||
|
self.menu_visible = False
|
||||||
|
else:
|
||||||
|
self.menu_frame.lift()
|
||||||
|
self.menu_visible = True
|
||||||
|
self.populate_menu()
|
||||||
|
|
||||||
|
def populate_menu(self):
|
||||||
|
# Очистка меню
|
||||||
|
for widget in self.menu_frame.winfo_children():
|
||||||
|
widget.destroy()
|
||||||
|
|
||||||
|
# Список разделов и их элементов
|
||||||
|
menu_sections = [
|
||||||
|
("Работа с базой данных", [
|
||||||
|
("Редактирование пользователей", self.manage_users),
|
||||||
|
("Управление вопросами", self.manage_questions),
|
||||||
|
("Управление собаками", self.manage_dogs),
|
||||||
|
("Просмотр таблиц", self.view_tables),
|
||||||
|
]),
|
||||||
|
("Управление игровым контентом", [
|
||||||
|
("Создание и настройка уровней", lambda: feature_in_development_admin(self.main_frame)),
|
||||||
|
("Настройка параметров собаки", lambda: feature_in_development_admin(self.main_frame)),
|
||||||
|
]),
|
||||||
|
("Управление интерфейсом пользователя", [
|
||||||
|
("Добавление подсказок в интерфейс", lambda: feature_in_development_admin(self.main_frame)),
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
# Определяем максимальную ширину текста для настройки ширины меню и кнопок
|
||||||
|
max_text_length = max(
|
||||||
|
len(title) for title, items in menu_sections
|
||||||
|
) + max(
|
||||||
|
max(len(text) for text, _ in items) for _, items in menu_sections
|
||||||
|
)
|
||||||
|
menu_width = max(300, max_text_length * 10) # Устанавливаем минимальную ширину
|
||||||
|
|
||||||
|
# Обновляем ширину меню
|
||||||
|
self.menu_frame.config(width=menu_width)
|
||||||
|
|
||||||
|
# Высота одной кнопки и отступов
|
||||||
|
button_height = 40
|
||||||
|
button_spacing = 10
|
||||||
|
section_spacing = 15
|
||||||
|
|
||||||
|
total_height = 0
|
||||||
|
|
||||||
|
for title, items in menu_sections:
|
||||||
|
section_label = tk.Label(
|
||||||
|
self.menu_frame,
|
||||||
|
text=title,
|
||||||
|
bg=MENU_COLOR,
|
||||||
|
fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 14, "bold"),
|
||||||
|
)
|
||||||
|
section_label.pack(fill="x", padx=10, pady=5)
|
||||||
|
|
||||||
|
for text, command in items:
|
||||||
|
item_button = tk.Button(
|
||||||
|
self.menu_frame,
|
||||||
|
text=text,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 12),
|
||||||
|
activebackground=BUTTON_COLOR,
|
||||||
|
activeforeground=TEXT_COLOR,
|
||||||
|
bd=0,
|
||||||
|
command=command # Используем lambda, чтобы передать команду без аргументов
|
||||||
|
)
|
||||||
|
item_button.pack(fill="x", padx=20, pady=5)
|
||||||
|
|
||||||
|
# Кнопка "Выйти" внизу меню
|
||||||
|
exit_button = tk.Button(
|
||||||
|
self.menu_frame,
|
||||||
|
text="Выйти",
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 12),
|
||||||
|
activebackground=BUTTON_COLOR,
|
||||||
|
activeforeground=TEXT_COLOR,
|
||||||
|
bd=0,
|
||||||
|
command=self.exit_app
|
||||||
|
)
|
||||||
|
exit_button.pack(side="bottom", padx=10, pady=20) # Размещение внизу
|
||||||
|
|
||||||
|
def create_nav_button(self, text, command):
|
||||||
|
"""Создание кнопки навигации."""
|
||||||
|
button = tk.Button(
|
||||||
|
self.top_bar,
|
||||||
|
text=text,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 14),
|
||||||
|
activebackground=BUTTON_COLOR,
|
||||||
|
activeforeground=TEXT_COLOR,
|
||||||
|
bd=0,
|
||||||
|
padx=10,
|
||||||
|
pady=5,
|
||||||
|
command=command # Передаем функцию напрямую
|
||||||
|
)
|
||||||
|
button.pack(side="left", padx=10, pady=10)
|
||||||
|
|
||||||
|
def open_manage_dogs_window(self, frame):
|
||||||
|
"""Открыть окно для управления собаками."""
|
||||||
|
self.manage_dogs()
|
||||||
|
|
||||||
|
def manage_ui_tips(self, frame):
|
||||||
|
# Пример логики для управления подсказками
|
||||||
|
print("Управление подсказками интерфейса.")
|
||||||
|
# Код для управления подсказками (например, скрытие или показ подсказок)
|
||||||
|
tk.Label(frame, text="Здесь будут подсказки для интерфейса", bg=BACKGROUND_COLOR, fg=TEXT_COLOR, font=("Comic Sans MS", 16)).pack()
|
||||||
|
|
||||||
|
def show_notifications(self, frame):
|
||||||
|
"""Отображение экрана уведомлений"""
|
||||||
|
clear_frame(frame) # Очищаем текущий экран
|
||||||
|
tk.Label(
|
||||||
|
frame,
|
||||||
|
text="Модуль <Уведомления> в разработке.\nВ планах реализовать: создание оповещений для пользователей (обновления, новости), сообщения от БД (корректность работы)",
|
||||||
bg=BACKGROUND_COLOR,
|
bg=BACKGROUND_COLOR,
|
||||||
fg=PRIMARY_COLOR,
|
fg=TEXT_COLOR,
|
||||||
font=FONT,
|
font=("Comic Sans MS", 16)
|
||||||
)
|
).pack(expand=True)
|
||||||
title.pack(pady=50)
|
|
||||||
|
|
||||||
# Кнопка для управления вопросами
|
def show_security(self, frame):
|
||||||
manage_questions_button = tk.Button(
|
"""Отображение экрана безопасности"""
|
||||||
self.current_frame,
|
clear_frame(frame) # Очищаем текущий экран
|
||||||
text="Управление вопросами",
|
tk.Label(
|
||||||
|
frame,
|
||||||
|
text="Модуль <Безопасность> в разработке.\nВ планах реализовать: управление доступом (создание других админов, смена пароля администратора).",
|
||||||
|
bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 16)
|
||||||
|
).pack(expand=True)
|
||||||
|
|
||||||
|
def change_ui_settings(self, frame):
|
||||||
|
clear_frame(frame)
|
||||||
|
"""Метод для изменения цветовой схемы, фона и логотипа"""
|
||||||
|
print("Изменение UI настроек") # Пока просто тестовый вывод
|
||||||
|
|
||||||
|
def exit_app(self):
|
||||||
|
"""Закрыть приложение."""
|
||||||
|
self.root.quit()
|
||||||
|
|
||||||
|
# Метод для авторизации под пользователем
|
||||||
|
def open_user_session(self):
|
||||||
|
"""Открыть новую сессию пользователя."""
|
||||||
|
user_login_window = tk.Toplevel(self.root)
|
||||||
|
user_login_window.title("Авторизация пользователя")
|
||||||
|
user_login_window.geometry("400x300")
|
||||||
|
user_login_window.configure(bg=BACKGROUND_COLOR)
|
||||||
|
|
||||||
|
tk.Label(
|
||||||
|
user_login_window,
|
||||||
|
text="Введите логин пользователя:",
|
||||||
|
bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 12)
|
||||||
|
).pack(pady=20)
|
||||||
|
|
||||||
|
user_login_entry = tk.Entry(user_login_window, font=("Comic Sans MS", 12))
|
||||||
|
user_login_entry.pack(pady=10)
|
||||||
|
|
||||||
|
def open_user_interface():
|
||||||
|
login = user_login_entry.get() # Получаем логин из поля ввода
|
||||||
|
user_id = check_user(login) # Передаем логин для проверки
|
||||||
|
|
||||||
|
if user_id:
|
||||||
|
user_login_window.destroy()
|
||||||
|
user_window = tk.Toplevel(self.root)
|
||||||
|
from src.ui.user_ui.main_menu import UserApp
|
||||||
|
UserApp(user_window, user_id=user_id)
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Ошибка", "Пользователь не найден.")
|
||||||
|
|
||||||
|
tk.Button(
|
||||||
|
user_login_window,
|
||||||
|
text="Открыть сессию",
|
||||||
bg=BUTTON_COLOR,
|
bg=BUTTON_COLOR,
|
||||||
fg=BUTTON_TEXT_COLOR,
|
fg=TEXT_COLOR,
|
||||||
font=FONT,
|
font=("Comic Sans MS", 12),
|
||||||
command=self.manage_questions,
|
command=open_user_interface
|
||||||
)
|
).pack(pady=20)
|
||||||
manage_questions_button.pack(pady=20)
|
|
||||||
|
|
||||||
# Кнопка для управления пользователями
|
tk.Button(
|
||||||
manage_users_button = tk.Button(
|
user_login_window,
|
||||||
self.current_frame,
|
text="Отмена",
|
||||||
text="Управление пользователями",
|
|
||||||
bg=BUTTON_COLOR,
|
bg=BUTTON_COLOR,
|
||||||
fg=BUTTON_TEXT_COLOR,
|
fg=TEXT_COLOR,
|
||||||
font=FONT,
|
font=("Comic Sans MS", 12),
|
||||||
command=self.manage_users,
|
command=user_login_window.destroy
|
||||||
)
|
).pack(pady=10)
|
||||||
manage_users_button.pack(pady=20)
|
|
||||||
|
|
||||||
def manage_questions(self):
|
|
||||||
"""Управление вопросами в игре."""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def manage_users(self):
|
def manage_users(self):
|
||||||
"""Управление пользователями игры."""
|
"""Управление пользователями."""
|
||||||
pass
|
clear_frame(self.main_frame)
|
||||||
|
|
||||||
|
tk.Label(self.main_frame, text="Управление пользователями", font=("Comic Sans MS", 16), bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR).pack()
|
||||||
|
|
||||||
|
# Кнопка добавления нового пользователя
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Добавить пользователя",
|
||||||
|
command=self.open_add_user_window,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
# Кнопка обновления списка
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Обновить список",
|
||||||
|
command=self.manage_users, # Перезагрузка данных
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
users = get_all_users() # Получение списка пользователей
|
||||||
|
|
||||||
|
if not users:
|
||||||
|
tk.Label(self.main_frame, text="Нет пользователей в базе данных.", bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR).pack()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Отображение данных в таблице
|
||||||
|
table = ttk.Treeview(self.main_frame, columns=("ID", "Логин", "Имя пользователя", "Уровень"), show="headings")
|
||||||
|
table.heading("ID", text="ID")
|
||||||
|
table.heading("Логин", text="Логин")
|
||||||
|
table.heading("Имя пользователя", text="Имя пользователя")
|
||||||
|
table.heading("Уровень", text="Уровень")
|
||||||
|
table.pack(fill="both", expand=True, pady=10)
|
||||||
|
|
||||||
|
# Очистка старых записей из таблицы
|
||||||
|
for row in table.get_children():
|
||||||
|
table.delete(row)
|
||||||
|
|
||||||
|
# Добавление данных из базы
|
||||||
|
for user in users:
|
||||||
|
table.insert("", "end", values=(user.user_id, user.auth.login, user.username, user.level))
|
||||||
|
|
||||||
|
def delete_selected():
|
||||||
|
selected_item = table.selection()
|
||||||
|
if not selected_item:
|
||||||
|
messagebox.showwarning("Удаление", "Выберите пользователя для удаления.")
|
||||||
|
return
|
||||||
|
user_id = table.item(selected_item, "values")[0]
|
||||||
|
success, message = delete_user(user_id)
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("Успех", message)
|
||||||
|
self.manage_users() # Обновление списка
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Ошибка", message)
|
||||||
|
|
||||||
|
# Кнопка удаления
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Удалить выбранного пользователя",
|
||||||
|
command=delete_selected,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
def manage_questions(self):
|
||||||
|
"""Управление вопросами."""
|
||||||
|
clear_frame(self.main_frame)
|
||||||
|
|
||||||
|
tk.Label(self.main_frame, text="Управление вопросами", font=("Comic Sans MS", 16), bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR).pack()
|
||||||
|
|
||||||
|
# Кнопка добавления нового вопроса
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Добавить вопрос",
|
||||||
|
command=self.open_add_question_window,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
# Кнопка обновления списка
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Обновить список",
|
||||||
|
command=self.manage_questions, # Перезагрузка данных
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
questions = get_all_questions() # Получение списка вопросов
|
||||||
|
|
||||||
|
if not questions:
|
||||||
|
tk.Label(self.main_frame, text="Нет вопросов в базе данных.", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Отображение данных в таблице
|
||||||
|
table = ttk.Treeview(self.main_frame, columns=("ID", "Вопрос", "Полезная информация"), show="headings")
|
||||||
|
table.heading("ID", text="ID")
|
||||||
|
table.heading("Вопрос", text="Вопрос")
|
||||||
|
table.heading("Полезная информация", text="Полезная информация")
|
||||||
|
table.pack(fill="both", expand=True, pady=10)
|
||||||
|
|
||||||
|
# Очистка таблицы перед заполнением новыми данными
|
||||||
|
for row in table.get_children():
|
||||||
|
table.delete(row)
|
||||||
|
|
||||||
|
for question in questions:
|
||||||
|
table.insert("", "end", values=(question.question_id, question.question_text, question.helpful_info))
|
||||||
|
|
||||||
|
def delete_selected():
|
||||||
|
selected_item = table.selection()
|
||||||
|
if not selected_item:
|
||||||
|
messagebox.showwarning("Удаление", "Выберите вопрос для удаления.")
|
||||||
|
return
|
||||||
|
|
||||||
|
question_id = table.item(selected_item, "values")[0] # Получение ID вопроса
|
||||||
|
success, message = delete_question(question_id) # Вызов метода для удаления вопроса
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("Успех", message)
|
||||||
|
self.manage_questions() # Обновление списка вопросов
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Ошибка", message)
|
||||||
|
|
||||||
|
# Кнопка удаления
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Удалить выбранный вопрос",
|
||||||
|
command=delete_selected,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
def manage_dogs(self):
|
||||||
|
"""Управление породами собак."""
|
||||||
|
clear_frame(self.main_frame)
|
||||||
|
|
||||||
|
# Заголовок
|
||||||
|
tk.Label(self.main_frame, text="Управление породами собак", font=("Comic Sans MS", 16), bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR).pack()
|
||||||
|
|
||||||
|
# Функция удаления выбранной породы
|
||||||
|
def delete_selected():
|
||||||
|
selected_item = table.selection()
|
||||||
|
if not selected_item:
|
||||||
|
messagebox.showwarning("Удаление", "Выберите породу для удаления.")
|
||||||
|
return
|
||||||
|
dog_id = table.item(selected_item, "values")[0] # ID породы
|
||||||
|
success, message = delete_dog(dog_id)
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("Успех", message)
|
||||||
|
self.manage_dogs() # Обновление списка
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Ошибка", message)
|
||||||
|
|
||||||
|
# Функция редактирования выбранной породы
|
||||||
|
def edit_selected():
|
||||||
|
selected_item = table.selection()
|
||||||
|
if not selected_item:
|
||||||
|
messagebox.showwarning("Редактирование", "Выберите породу для редактирования.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Получение данных выбранной породы
|
||||||
|
dog_data = table.item(selected_item, "values")
|
||||||
|
|
||||||
|
# Пример dog_data: ('dog_id', 'breed', 'characteristics', 'behavior', 'care_info', 'admin_comments')
|
||||||
|
|
||||||
|
if len(dog_data) < 6:
|
||||||
|
messagebox.showwarning("Ошибка", "Недостаточно данных для редактирования.")
|
||||||
|
return
|
||||||
|
|
||||||
|
dog_id = dog_data[0]
|
||||||
|
breed = dog_data[1]
|
||||||
|
characteristics = dog_data[2]
|
||||||
|
behavior = dog_data[3]
|
||||||
|
care_info = dog_data[4] # Дополнительная информация о породе
|
||||||
|
admin_comments = dog_data[5] # Комментарии администратора
|
||||||
|
|
||||||
|
# Вызов функции открытия окна редактирования породы, передавая все необходимые данные
|
||||||
|
self.open_edit_dog_window(dog_id, breed, characteristics, behavior, care_info, admin_comments)
|
||||||
|
|
||||||
|
# Кнопка добавления новой породы
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Добавить породу",
|
||||||
|
command=self.open_add_dog_window,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
# Кнопка обновления списка
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Обновить список",
|
||||||
|
command=self.manage_dogs, # Повторный вызов для обновления данных
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
# Кнопка удаления
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Удалить выбранную породу",
|
||||||
|
command=delete_selected,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
# Кнопка редактирования
|
||||||
|
tk.Button(
|
||||||
|
self.main_frame,
|
||||||
|
text="Редактировать выбранную породу",
|
||||||
|
command=edit_selected,
|
||||||
|
bg=BUTTON_COLOR,
|
||||||
|
fg=TEXT_COLOR
|
||||||
|
).pack(pady=10)
|
||||||
|
|
||||||
|
# Получение данных из базы
|
||||||
|
dogs = get_all_dogs()
|
||||||
|
|
||||||
|
if not dogs:
|
||||||
|
tk.Label(self.main_frame, text="Нет записей о породах в базе данных.", bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR).pack()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Создание таблицы
|
||||||
|
table = ttk.Treeview(self.main_frame, columns=(
|
||||||
|
"ID", "Порода", "Характеристики", "Поведение", "Информация по уходу", "Комментарии"), show="headings")
|
||||||
|
table.heading("ID", text="ID")
|
||||||
|
table.heading("Порода", text="Порода")
|
||||||
|
table.heading("Характеристики", text="Характеристики")
|
||||||
|
table.heading("Поведение", text="Поведение")
|
||||||
|
table.heading("Информация по уходу", text="Информация по уходу")
|
||||||
|
table.heading("Комментарии", text="Комментарии")
|
||||||
|
table.pack(fill="both", expand=True, pady=10)
|
||||||
|
|
||||||
|
# Заполнение таблицы данными о породах
|
||||||
|
for dog in dogs:
|
||||||
|
table.insert("", "end", values=(
|
||||||
|
dog.dog_id, dog.breed, dog.characteristics, dog.behavior, dog.care_info, dog.admin_comments))
|
||||||
|
|
||||||
|
def open_edit_dog_window(self, dog_id, breed, characteristics, behavior, care_info, admin_comments):
|
||||||
|
"""Открыть окно редактирования данных о породе собак."""
|
||||||
|
edit_dog_window = tk.Toplevel(self.root)
|
||||||
|
edit_dog_window.title("Редактировать данные породы")
|
||||||
|
edit_dog_window.geometry("500x400")
|
||||||
|
edit_dog_window.configure(bg=BACKGROUND_COLOR)
|
||||||
|
|
||||||
|
fields = {
|
||||||
|
"Порода": (breed, tk.Entry(edit_dog_window, font=("Comic Sans MS", 12))),
|
||||||
|
"Характеристики": (characteristics, tk.Entry(edit_dog_window, font=("Comic Sans MS", 12))),
|
||||||
|
"Поведение": (behavior, tk.Entry(edit_dog_window, font=("Comic Sans MS", 12))),
|
||||||
|
"Уход": (care_info, tk.Entry(edit_dog_window, font=("Comic Sans MS", 12))),
|
||||||
|
"Комментарии администратора": (admin_comments, tk.Entry(edit_dog_window, font=("Comic Sans MS", 12))),
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, (label_text, (value, entry)) in enumerate(fields.items()):
|
||||||
|
tk.Label(edit_dog_window, text=label_text, bg=BACKGROUND_COLOR, fg=TEXT_COLOR,
|
||||||
|
font=("Comic Sans MS", 12)).grid(row=idx, column=0, pady=10, padx=10)
|
||||||
|
entry.insert(0, value)
|
||||||
|
entry.grid(row=idx, column=1, pady=10, padx=10)
|
||||||
|
|
||||||
|
def save_changes():
|
||||||
|
updated_data = {key: entry.get() for key, (_, entry) in fields.items()}
|
||||||
|
success, message = update_dog_info(dog_id, updated_data["Порода"], updated_data["Характеристики"])
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("Успех", message)
|
||||||
|
edit_dog_window.destroy()
|
||||||
|
self.manage_dogs() # Обновление списка пород
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Ошибка", message)
|
||||||
|
|
||||||
|
tk.Button(edit_dog_window, text="Сохранить", command=save_changes, bg=BUTTON_COLOR, fg=TEXT_COLOR).grid(
|
||||||
|
row=len(fields), column=0, pady=20)
|
||||||
|
tk.Button(edit_dog_window, text="Отмена", command=edit_dog_window.destroy, bg=BUTTON_COLOR, fg=TEXT_COLOR).grid(
|
||||||
|
row=len(fields), column=1, pady=20)
|
||||||
|
|
||||||
|
def view_tables(self):
|
||||||
|
"""Просмотр всех таблиц."""
|
||||||
|
clear_frame(self.main_frame)
|
||||||
|
|
||||||
|
tk.Label(self.main_frame, text="Просмотр всех таблиц", font=("Comic Sans MS", 16), bg=BACKGROUND_COLOR,
|
||||||
|
fg=TEXT_COLOR).pack()
|
||||||
|
|
||||||
|
# Создаём вкладки для отображения таблиц
|
||||||
|
tab_control = ttk.Notebook(self.main_frame)
|
||||||
|
|
||||||
|
# Таблица пользователей
|
||||||
|
users_frame = ttk.Frame(tab_control)
|
||||||
|
tab_control.add(users_frame, text="Пользователи")
|
||||||
|
users_data = get_all_users()
|
||||||
|
if users_data:
|
||||||
|
self.create_table_view(users_frame, users_data, ["user_id", "login", "username", "level"])
|
||||||
|
else:
|
||||||
|
tk.Label(users_frame, text="Нет данных о пользователях.", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack()
|
||||||
|
|
||||||
|
# Таблица собак
|
||||||
|
dogs_frame = ttk.Frame(tab_control)
|
||||||
|
tab_control.add(dogs_frame, text="Породы собак")
|
||||||
|
dogs_data = get_all_dogs()
|
||||||
|
if dogs_data:
|
||||||
|
self.create_table_view(dogs_frame, dogs_data, ["dog_id", "breed", "characteristics", "behavior"])
|
||||||
|
else:
|
||||||
|
tk.Label(dogs_frame, text="Нет данных о породах собак.", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack()
|
||||||
|
|
||||||
|
# Таблица вопросов
|
||||||
|
questions_frame = ttk.Frame(tab_control)
|
||||||
|
tab_control.add(questions_frame, text="Вопросы")
|
||||||
|
questions_data = get_all_questions()
|
||||||
|
if questions_data:
|
||||||
|
self.create_table_view(questions_frame, questions_data, ["question_id", "question_text", "helpful_info"])
|
||||||
|
else:
|
||||||
|
tk.Label(questions_frame, text="Нет данных о вопросах.", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack()
|
||||||
|
|
||||||
|
tab_control.pack(expand=True, fill="both")
|
||||||
|
|
||||||
|
def create_table_view(self, frame, data, columns):
|
||||||
|
"""Создание и отображение таблицы на основе данных и столбцов."""
|
||||||
|
# Создаём таблицу
|
||||||
|
table = ttk.Treeview(frame, columns=columns, show="headings")
|
||||||
|
|
||||||
|
# Заголовки таблицы
|
||||||
|
for col in columns:
|
||||||
|
table.heading(col, text=col)
|
||||||
|
table.column(col, anchor="center") # Выравнивание заголовков по центру
|
||||||
|
|
||||||
|
# Заполнение таблицы данными
|
||||||
|
for row in data:
|
||||||
|
if isinstance(row, dict): # Если данные представлены в виде словаря
|
||||||
|
values = [row.get(col, "") for col in columns]
|
||||||
|
elif hasattr(row, "__dict__"): # Если данные — это объект SQLAlchemy
|
||||||
|
values = [getattr(row, col, "") for col in columns]
|
||||||
|
else:
|
||||||
|
values = row if isinstance(row, (list, tuple)) else []
|
||||||
|
|
||||||
|
table.insert("", "end", values=values)
|
||||||
|
|
||||||
|
# Устанавливаем таблицу в интерфейс
|
||||||
|
table.pack(fill="both", expand=True, pady=10)
|
||||||
|
|
||||||
|
def open_add_dog_window(self):
|
||||||
|
"""Открыть окно для добавления новой собаки."""
|
||||||
|
add_dog_window = tk.Toplevel(self.root)
|
||||||
|
add_dog_window.title("Добавить новую собаку")
|
||||||
|
add_dog_window.geometry("400x300")
|
||||||
|
add_dog_window.configure(bg=BACKGROUND_COLOR)
|
||||||
|
|
||||||
|
tk.Label(add_dog_window, text="Порода", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
breed_entry = tk.Entry(add_dog_window, font=("Comic Sans MS", 12))
|
||||||
|
breed_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_dog_window, text="Характеристики", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
characteristics_entry = tk.Entry(add_dog_window, font=("Comic Sans MS", 12))
|
||||||
|
characteristics_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_dog_window, text="Поведение", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
behavior_entry = tk.Entry(add_dog_window, font=("Comic Sans MS", 12))
|
||||||
|
behavior_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_dog_window, text="Уход", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
care_info_entry = tk.Entry(add_dog_window, font=("Comic Sans MS", 12))
|
||||||
|
care_info_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_dog_window, text="Комментарии администратора", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
admin_comments_entry = tk.Entry(add_dog_window, font=("Comic Sans MS", 12))
|
||||||
|
admin_comments_entry.pack(pady=5)
|
||||||
|
|
||||||
|
def save_dog():
|
||||||
|
dog_data = {
|
||||||
|
'breed': breed_entry.get(),
|
||||||
|
'characteristics': characteristics_entry.get(),
|
||||||
|
'behavior': behavior_entry.get(),
|
||||||
|
'care_info': care_info_entry.get(),
|
||||||
|
'admin_comments': admin_comments_entry.get()
|
||||||
|
}
|
||||||
|
add_dog_to_db(dog_data)
|
||||||
|
add_dog_window.destroy()
|
||||||
|
|
||||||
|
def cancel_add():
|
||||||
|
add_dog_window.destroy()
|
||||||
|
|
||||||
|
save_button = tk.Button(add_dog_window, text="Сохранить", command=save_dog, bg=BUTTON_COLOR, fg=TEXT_COLOR)
|
||||||
|
save_button.pack(pady=20)
|
||||||
|
|
||||||
|
cancel_button = tk.Button(add_dog_window, text="Отменить", command=cancel_add, bg=BUTTON_COLOR, fg=TEXT_COLOR)
|
||||||
|
cancel_button.pack(pady=10)
|
||||||
|
|
||||||
|
|
||||||
|
def open_add_user_window(self):
|
||||||
|
"""Открыть окно для добавления нового пользователя."""
|
||||||
|
add_user_window = tk.Toplevel(self.root)
|
||||||
|
add_user_window.title("Добавить нового пользователя")
|
||||||
|
add_user_window.geometry("400x300")
|
||||||
|
add_user_window.configure(bg=BACKGROUND_COLOR)
|
||||||
|
|
||||||
|
tk.Label(add_user_window, text="Логин", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
login_entry = tk.Entry(add_user_window, font=("Comic Sans MS", 12))
|
||||||
|
login_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_user_window, text="Пароль", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
password_entry = tk.Entry(add_user_window, font=("Comic Sans MS", 12), show="*")
|
||||||
|
password_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_user_window, text="Имя пользователя", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
username_entry = tk.Entry(add_user_window, font=("Comic Sans MS", 12))
|
||||||
|
username_entry.pack(pady=5)
|
||||||
|
|
||||||
|
def save_user():
|
||||||
|
user_data = {
|
||||||
|
'login': login_entry.get(),
|
||||||
|
'password': password_entry.get(),
|
||||||
|
'username': username_entry.get(),
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
add_user_to_db(user_data)
|
||||||
|
messagebox.showinfo("Успех", "Пользователь успешно добавлен.")
|
||||||
|
add_user_window.destroy()
|
||||||
|
self.manage_users() # Обновить список пользователей
|
||||||
|
except Exception as e:
|
||||||
|
messagebox.showerror("Ошибка", f"Не удалось добавить пользователя: {e}")
|
||||||
|
|
||||||
|
def cancel_add():
|
||||||
|
add_user_window.destroy()
|
||||||
|
|
||||||
|
save_button = tk.Button(add_user_window, text="Сохранить", command=save_user, bg=BUTTON_COLOR, fg=TEXT_COLOR)
|
||||||
|
save_button.pack(pady=20)
|
||||||
|
|
||||||
|
cancel_button = tk.Button(add_user_window, text="Отменить", command=cancel_add, bg=BUTTON_COLOR, fg=TEXT_COLOR)
|
||||||
|
cancel_button.pack(pady=10)
|
||||||
|
|
||||||
|
def open_add_question_window(self):
|
||||||
|
"""Открыть окно для добавления нового вопроса."""
|
||||||
|
add_question_window = tk.Toplevel(self.root)
|
||||||
|
add_question_window.title("Добавить новый вопрос")
|
||||||
|
add_question_window.geometry("400x300")
|
||||||
|
add_question_window.configure(bg=BACKGROUND_COLOR)
|
||||||
|
|
||||||
|
tk.Label(add_question_window, text="ID собаки", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
dog_id_entry = tk.Entry(add_question_window, font=("Comic Sans MS", 12))
|
||||||
|
dog_id_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_question_window, text="Вопрос", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
question_text_entry = tk.Entry(add_question_window, font=("Comic Sans MS", 12))
|
||||||
|
question_text_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_question_window, text="Изображение URL", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
image_url_entry = tk.Entry(add_question_window, font=("Comic Sans MS", 12))
|
||||||
|
image_url_entry.pack(pady=5)
|
||||||
|
|
||||||
|
tk.Label(add_question_window, text="Полезная информация", bg=BACKGROUND_COLOR, fg=TEXT_COLOR).pack(pady=10)
|
||||||
|
helpful_info_entry = tk.Entry(add_question_window, font=("Comic Sans MS", 12))
|
||||||
|
helpful_info_entry.pack(pady=5)
|
||||||
|
|
||||||
|
def save_question():
|
||||||
|
question_data = {
|
||||||
|
'dog_id': int(dog_id_entry.get()),
|
||||||
|
'question_text': question_text_entry.get(),
|
||||||
|
'image_url': image_url_entry.get(),
|
||||||
|
'helpful_info': helpful_info_entry.get()
|
||||||
|
}
|
||||||
|
add_question_to_db(question_data)
|
||||||
|
add_question_window.destroy()
|
||||||
|
|
||||||
|
def cancel_add():
|
||||||
|
add_question_window.destroy()
|
||||||
|
|
||||||
|
save_button = tk.Button(add_question_window, text="Сохранить", command=save_question, bg=BUTTON_COLOR, fg=TEXT_COLOR)
|
||||||
|
save_button.pack(pady=20)
|
||||||
|
|
||||||
|
cancel_button = tk.Button(add_question_window, text="Отменить", command=cancel_add, bg=BUTTON_COLOR, fg=TEXT_COLOR)
|
||||||
|
cancel_button.pack(pady=10)
|
||||||
|
|
||||||
def clear_frame(self):
|
|
||||||
"""Очистить текущий фрейм."""
|
|
||||||
if hasattr(self, 'current_frame') and self.current_frame:
|
|
||||||
self.current_frame.destroy()
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from config import BACKGROUND_COLOR, PRIMARY_COLOR, BUTTON_COLOR, BUTTON_TEXT_COLOR, FONT, BIG_FONT, ADMIN_LOGIN, ADMIN_PASSWORD
|
from config import BACKGROUND_COLOR, PRIMARY_COLOR, BUTTON_COLOR, BUTTON_TEXT_COLOR, FONT, BIG_FONT, ADMIN_LOGIN, ADMIN_PASSWORD
|
||||||
|
from src.auth import login_user
|
||||||
from src.ui.admin_ui import AdminApp # Импорт интерфейса администратора
|
from src.ui.admin_ui import AdminApp # Импорт интерфейса администратора
|
||||||
from database.db_events import create_user, check_user
|
from database.db_events import create_user
|
||||||
from src.ui.user_ui import UserApp
|
from src.ui.user_ui.main_menu import UserApp
|
||||||
|
|
||||||
class DogAcademyApp:
|
class DogAcademyApp:
|
||||||
def __init__(self, root):
|
def __init__(self, root, user_id=None):
|
||||||
|
"""Инициализация приложения."""
|
||||||
self.root = root
|
self.root = root
|
||||||
|
self.user_id = user_id
|
||||||
self.root.title("Dog Academy Game")
|
self.root.title("Dog Academy Game")
|
||||||
self.root.geometry("1920x1080")
|
self.root.geometry("1920x1080")
|
||||||
self.root.configure(bg=BACKGROUND_COLOR)
|
self.root.configure(bg=BACKGROUND_COLOR)
|
||||||
|
|
@ -20,12 +23,11 @@ class DogAcademyApp:
|
||||||
self.current_frame.destroy()
|
self.current_frame.destroy()
|
||||||
|
|
||||||
def show_main_menu(self):
|
def show_main_menu(self):
|
||||||
"""Показать главное меню с названием игры и кнопками."""
|
"""Показать главное меню."""
|
||||||
self.clear_frame()
|
self.clear_frame()
|
||||||
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
||||||
self.current_frame.pack(expand=True)
|
self.current_frame.pack(expand=True)
|
||||||
|
|
||||||
# Название игры
|
|
||||||
title = tk.Label(
|
title = tk.Label(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Dog Academy Game",
|
text="Dog Academy Game",
|
||||||
|
|
@ -35,7 +37,6 @@ class DogAcademyApp:
|
||||||
)
|
)
|
||||||
title.pack(pady=50)
|
title.pack(pady=50)
|
||||||
|
|
||||||
# Кнопка "Войти"
|
|
||||||
login_button = tk.Button(
|
login_button = tk.Button(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Войти",
|
text="Войти",
|
||||||
|
|
@ -46,7 +47,6 @@ class DogAcademyApp:
|
||||||
)
|
)
|
||||||
login_button.pack(pady=20)
|
login_button.pack(pady=20)
|
||||||
|
|
||||||
# Кнопка "Зарегистрироваться"
|
|
||||||
register_button = tk.Button(
|
register_button = tk.Button(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Зарегистрироваться",
|
text="Зарегистрироваться",
|
||||||
|
|
@ -63,7 +63,6 @@ class DogAcademyApp:
|
||||||
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
||||||
self.current_frame.pack(expand=True)
|
self.current_frame.pack(expand=True)
|
||||||
|
|
||||||
# Заголовок
|
|
||||||
title = tk.Label(
|
title = tk.Label(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Авторизация",
|
text="Авторизация",
|
||||||
|
|
@ -73,15 +72,16 @@ class DogAcademyApp:
|
||||||
)
|
)
|
||||||
title.pack(pady=50)
|
title.pack(pady=50)
|
||||||
|
|
||||||
# Логин
|
login_label = tk.Label(self.current_frame, text="Логин:", bg=BACKGROUND_COLOR, fg=PRIMARY_COLOR, font=FONT)
|
||||||
|
login_label.pack()
|
||||||
self.login_entry = tk.Entry(self.current_frame, font=FONT)
|
self.login_entry = tk.Entry(self.current_frame, font=FONT)
|
||||||
self.login_entry.pack(pady=10)
|
self.login_entry.pack(pady=10)
|
||||||
|
|
||||||
# Пароль
|
password_label = tk.Label(self.current_frame, text="Пароль:", bg=BACKGROUND_COLOR, fg=PRIMARY_COLOR, font=FONT)
|
||||||
|
password_label.pack()
|
||||||
self.password_entry = tk.Entry(self.current_frame, show="*", font=FONT)
|
self.password_entry = tk.Entry(self.current_frame, show="*", font=FONT)
|
||||||
self.password_entry.pack(pady=10)
|
self.password_entry.pack(pady=10)
|
||||||
|
|
||||||
# Кнопка "Показать пароль"
|
|
||||||
show_password_button = tk.Button(
|
show_password_button = tk.Button(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Показать пароль",
|
text="Показать пароль",
|
||||||
|
|
@ -92,7 +92,6 @@ class DogAcademyApp:
|
||||||
)
|
)
|
||||||
show_password_button.pack(pady=10)
|
show_password_button.pack(pady=10)
|
||||||
|
|
||||||
# Кнопка "Войти"
|
|
||||||
login_button = tk.Button(
|
login_button = tk.Button(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Войти",
|
text="Войти",
|
||||||
|
|
@ -103,7 +102,6 @@ class DogAcademyApp:
|
||||||
)
|
)
|
||||||
login_button.pack(pady=20)
|
login_button.pack(pady=20)
|
||||||
|
|
||||||
# Кнопка "Вернуться на главную"
|
|
||||||
back_button = tk.Button(
|
back_button = tk.Button(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Вернуться на главную",
|
text="Вернуться на главную",
|
||||||
|
|
@ -128,17 +126,21 @@ class DogAcademyApp:
|
||||||
|
|
||||||
if login == ADMIN_LOGIN and password == ADMIN_PASSWORD:
|
if login == ADMIN_LOGIN and password == ADMIN_PASSWORD:
|
||||||
messagebox.showinfo("Успех", "Вы успешно авторизованы как администратор!")
|
messagebox.showinfo("Успех", "Вы успешно авторизованы как администратор!")
|
||||||
self.show_admin_panel() # Переходим к админ-панели
|
self.user_id = None # Администратору не нужен user_id
|
||||||
elif check_user(login, password):
|
self.show_admin_panel()
|
||||||
messagebox.showinfo("Успех", "Вы успешно авторизованы!")
|
|
||||||
self.show_user_dashboard() # Переходим к панели пользователя
|
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Ошибка", "Неверные данные. Попробуйте снова.")
|
success, user_id = login_user(login, password)
|
||||||
|
if success:
|
||||||
|
messagebox.showinfo("Успех", "Вы успешно авторизованы!")
|
||||||
|
self.user_id = user_id # Сохраняем user_id
|
||||||
|
self.show_user_dashboard()
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Ошибка", "Неверный логин или пароль.")
|
||||||
|
|
||||||
def show_admin_panel(self):
|
def show_admin_panel(self):
|
||||||
"""Отображение интерфейса администратора."""
|
"""Отображение интерфейса администратора."""
|
||||||
self.clear_frame()
|
self.clear_frame()
|
||||||
AdminApp(self.root) # Создаем экземпляр админ-панели
|
AdminApp(self.root)
|
||||||
|
|
||||||
def show_registration_screen(self):
|
def show_registration_screen(self):
|
||||||
"""Показать экран регистрации."""
|
"""Показать экран регистрации."""
|
||||||
|
|
@ -146,7 +148,6 @@ class DogAcademyApp:
|
||||||
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
||||||
self.current_frame.pack(expand=True)
|
self.current_frame.pack(expand=True)
|
||||||
|
|
||||||
# Заголовок
|
|
||||||
title = tk.Label(
|
title = tk.Label(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Регистрация",
|
text="Регистрация",
|
||||||
|
|
@ -156,26 +157,21 @@ class DogAcademyApp:
|
||||||
)
|
)
|
||||||
title.pack(pady=50)
|
title.pack(pady=50)
|
||||||
|
|
||||||
# Логин
|
login_label = tk.Label(self.current_frame, text="Логин:", bg=BACKGROUND_COLOR, fg=PRIMARY_COLOR, font=FONT)
|
||||||
|
login_label.pack()
|
||||||
self.reg_login_entry = tk.Entry(self.current_frame, font=FONT)
|
self.reg_login_entry = tk.Entry(self.current_frame, font=FONT)
|
||||||
self.reg_login_entry.pack(pady=10)
|
self.reg_login_entry.pack(pady=10)
|
||||||
|
|
||||||
# Пароль
|
password_label = tk.Label(self.current_frame, text="Пароль:", bg=BACKGROUND_COLOR, fg=PRIMARY_COLOR, font=FONT)
|
||||||
|
password_label.pack()
|
||||||
self.reg_password_entry = tk.Entry(self.current_frame, show="*", font=FONT)
|
self.reg_password_entry = tk.Entry(self.current_frame, show="*", font=FONT)
|
||||||
self.reg_password_entry.pack(pady=10)
|
self.reg_password_entry.pack(pady=10)
|
||||||
|
|
||||||
# Кнопка "Показать пароль"
|
username_label = tk.Label(self.current_frame, text="Никнейм:", bg=BACKGROUND_COLOR, fg=PRIMARY_COLOR, font=FONT)
|
||||||
show_password_button = tk.Button(
|
username_label.pack()
|
||||||
self.current_frame,
|
self.username_entry = tk.Entry(self.current_frame, font=FONT)
|
||||||
text="Показать пароль",
|
self.username_entry.pack(pady=10)
|
||||||
bg=BUTTON_COLOR,
|
|
||||||
fg=BUTTON_TEXT_COLOR,
|
|
||||||
font=FONT,
|
|
||||||
command=self.toggle_registration_password,
|
|
||||||
)
|
|
||||||
show_password_button.pack(pady=10)
|
|
||||||
|
|
||||||
# Кнопка "Зарегистрироваться"
|
|
||||||
register_button = tk.Button(
|
register_button = tk.Button(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Зарегистрироваться",
|
text="Зарегистрироваться",
|
||||||
|
|
@ -186,7 +182,6 @@ class DogAcademyApp:
|
||||||
)
|
)
|
||||||
register_button.pack(pady=20)
|
register_button.pack(pady=20)
|
||||||
|
|
||||||
# Кнопка "Вернуться на главную"
|
|
||||||
back_button = tk.Button(
|
back_button = tk.Button(
|
||||||
self.current_frame,
|
self.current_frame,
|
||||||
text="Вернуться на главную",
|
text="Вернуться на главную",
|
||||||
|
|
@ -208,15 +203,19 @@ class DogAcademyApp:
|
||||||
"""Регистрация нового пользователя."""
|
"""Регистрация нового пользователя."""
|
||||||
login = self.reg_login_entry.get()
|
login = self.reg_login_entry.get()
|
||||||
password = self.reg_password_entry.get()
|
password = self.reg_password_entry.get()
|
||||||
|
username = self.username_entry.get()
|
||||||
|
|
||||||
if login and password:
|
if login and password and username:
|
||||||
create_user(login, password)
|
success, message = create_user(login, password, username)
|
||||||
messagebox.showinfo("Успех", "Вы успешно зарегистрированы!")
|
if success:
|
||||||
self.show_login_screen()
|
messagebox.showinfo("Успех", message)
|
||||||
|
self.show_login_screen()
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Ошибка", message)
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Ошибка", "Пожалуйста, заполните все поля.")
|
messagebox.showerror("Ошибка", "Заполните все поля.")
|
||||||
|
|
||||||
def show_user_dashboard(self):
|
def show_user_dashboard(self):
|
||||||
"""Перейти к главному меню пользователя после авторизации."""
|
"""Переход к пользовательскому интерфейсу."""
|
||||||
UserApp(self.root, self)
|
self.clear_frame()
|
||||||
|
UserApp(self.root, self.user_id)
|
||||||
|
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
import tkinter as tk
|
|
||||||
from config import BACKGROUND_COLOR, PRIMARY_COLOR, BUTTON_COLOR, BUTTON_TEXT_COLOR, FONT
|
|
||||||
|
|
||||||
class UserApp:
|
|
||||||
def __init__(self, root, dog_academy_app):
|
|
||||||
self.root = root
|
|
||||||
self.dog_academy_app = dog_academy_app # Сохраняем ссылку на DogAcademyApp
|
|
||||||
self.show_user_dashboard()
|
|
||||||
|
|
||||||
def show_user_dashboard(self):
|
|
||||||
"""Показать интерфейс пользователя."""
|
|
||||||
self.clear_frame()
|
|
||||||
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
|
||||||
self.current_frame.pack(expand=True)
|
|
||||||
|
|
||||||
# Заголовок
|
|
||||||
title = tk.Label(
|
|
||||||
self.current_frame,
|
|
||||||
text="Главное меню",
|
|
||||||
bg=BACKGROUND_COLOR,
|
|
||||||
fg=PRIMARY_COLOR,
|
|
||||||
font=FONT,
|
|
||||||
)
|
|
||||||
title.pack(pady=50)
|
|
||||||
|
|
||||||
# Кнопка "Играть"
|
|
||||||
play_button = tk.Button(
|
|
||||||
self.current_frame,
|
|
||||||
text="Играть",
|
|
||||||
bg=BUTTON_COLOR,
|
|
||||||
fg=BUTTON_TEXT_COLOR,
|
|
||||||
font=FONT,
|
|
||||||
command=self.play_game,
|
|
||||||
)
|
|
||||||
play_button.pack(pady=20)
|
|
||||||
|
|
||||||
# Кнопка "Выход"
|
|
||||||
logout_button = tk.Button(
|
|
||||||
self.current_frame,
|
|
||||||
text="Выход",
|
|
||||||
bg=BUTTON_COLOR,
|
|
||||||
fg=BUTTON_TEXT_COLOR,
|
|
||||||
font=FONT,
|
|
||||||
command=self.dog_academy_app.show_main_menu, # Вызываем метод из DogAcademyApp
|
|
||||||
)
|
|
||||||
logout_button.pack(pady=20)
|
|
||||||
|
|
||||||
def play_game(self):
|
|
||||||
"""Запуск игры."""
|
|
||||||
# TODO: Логика игры
|
|
||||||
pass
|
|
||||||
|
|
||||||
def clear_frame(self):
|
|
||||||
"""Очистить текущий фрейм."""
|
|
||||||
if hasattr(self, 'current_frame') and self.current_frame:
|
|
||||||
self.current_frame.destroy()
|
|
||||||
BIN
src/ui/user_ui/__pycache__/game_ui.cpython-313.pyc
Normal file
BIN
src/ui/user_ui/__pycache__/knowledge_ui.cpython-313.pyc
Normal file
BIN
src/ui/user_ui/__pycache__/main_menu.cpython-313.pyc
Normal file
BIN
src/ui/user_ui/__pycache__/profile_ui.cpython-313.pyc
Normal file
BIN
src/ui/user_ui/__pycache__/shop_ui.cpython-313.pyc
Normal file
649
src/ui/user_ui/game_ui.py
Normal file
|
|
@ -0,0 +1,649 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
|
||||||
|
from PIL import Image, ImageTk
|
||||||
|
import random
|
||||||
|
import logging
|
||||||
|
from database.db_events import get_user_by_id, get_user_progress
|
||||||
|
from database.info.GameSessions_table import save_game_session
|
||||||
|
from src.user_functions.game_logs import setup_logging
|
||||||
|
from config import DOG_CHARACTERS, DONE, BONE, BACKGROUND_GAME
|
||||||
|
from src.utils import clear_frame
|
||||||
|
|
||||||
|
# Настройка логирования
|
||||||
|
setup_logging()
|
||||||
|
|
||||||
|
user = get_user_by_id(user_id=1)
|
||||||
|
if user:
|
||||||
|
print(f"Данные пользователя: {user}")
|
||||||
|
else:
|
||||||
|
print("Пользователь не найден")
|
||||||
|
|
||||||
|
class GameUI:
|
||||||
|
def __init__(self, root, user_id, return_to_main_menu_callback):
|
||||||
|
if not user_id:
|
||||||
|
raise ValueError("user_id отсутствует при инициализации GameUI!")
|
||||||
|
|
||||||
|
self.root = root
|
||||||
|
self.user_id = user_id
|
||||||
|
self.return_to_main_menu_callback = return_to_main_menu_callback
|
||||||
|
self.selected_dog = None
|
||||||
|
self.current_level = 1
|
||||||
|
self.completed_levels = set()
|
||||||
|
|
||||||
|
self.total_bones = 0
|
||||||
|
self.dog_position = [1, 1]
|
||||||
|
self.map_canvas = None
|
||||||
|
self.bones_positions = []
|
||||||
|
self.max_bones_per_level = 10
|
||||||
|
self.steps_taken = 0
|
||||||
|
self.user_data = get_user_by_id(self.user_id)
|
||||||
|
|
||||||
|
# Получаем прогресс пользователя
|
||||||
|
self.user_progress = get_user_progress(user_id)
|
||||||
|
self.max_unlocked_level = max([session.level for session in self.user_progress]) if self.user_progress else 1
|
||||||
|
|
||||||
|
# Добавляем атрибут is_replay
|
||||||
|
self.is_replay = False # По умолчанию нет повторного прохождения
|
||||||
|
|
||||||
|
# Изображения
|
||||||
|
self.done_image = ImageTk.PhotoImage(Image.open(DONE).resize((50, 50), Image.Resampling.LANCZOS))
|
||||||
|
self.bones_photo = ImageTk.PhotoImage(Image.open(BONE).resize((50, 50), Image.Resampling.LANCZOS))
|
||||||
|
|
||||||
|
# Размер сетки
|
||||||
|
self.grid_size = 60
|
||||||
|
self.cols = 32
|
||||||
|
self.rows = 18
|
||||||
|
|
||||||
|
# Настройки окна
|
||||||
|
self.root.geometry("1920x1080")
|
||||||
|
self.root.configure(bg="#E5E5E5")
|
||||||
|
|
||||||
|
# Флаги
|
||||||
|
self.is_pause_menu_open = False
|
||||||
|
self.is_victory_screen_open = False
|
||||||
|
self.is_game_active = False
|
||||||
|
|
||||||
|
# Привязка клавиш
|
||||||
|
self.root.bind("<KeyPress-w>", self.move_up)
|
||||||
|
self.root.bind("<KeyPress-s>", self.move_down)
|
||||||
|
self.root.bind("<KeyPress-a>", self.move_left)
|
||||||
|
self.root.bind("<KeyPress-d>", self.move_right)
|
||||||
|
self.root.bind("<Escape>", self.on_escape)
|
||||||
|
|
||||||
|
# Отображение начального экрана
|
||||||
|
self.show_dog_selection()
|
||||||
|
|
||||||
|
if self.user_data:
|
||||||
|
self.max_unlocked_level = self.user_data.level or 1
|
||||||
|
self.total_bones = sum([session.score for session in get_user_progress(self.user_id)])
|
||||||
|
else:
|
||||||
|
logging.warning("Данные пользователя не найдены")
|
||||||
|
|
||||||
|
def create_background(self):
|
||||||
|
"""Создаёт фон для игры."""
|
||||||
|
try:
|
||||||
|
bg_image = Image.open(BACKGROUND_GAME)
|
||||||
|
bg_photo = ImageTk.PhotoImage(bg_image.resize((1920, 1080), Image.Resampling.LANCZOS))
|
||||||
|
bg_label = tk.Label(self.root, image=bg_photo)
|
||||||
|
bg_label.image = bg_photo
|
||||||
|
bg_label.place(x=0, y=0, relwidth=1, relheight=1)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Ошибка загрузки фона: {e}")
|
||||||
|
|
||||||
|
def show_dog_selection(self):
|
||||||
|
"""Отображение выбора собаки пользователем."""
|
||||||
|
clear_frame(self.root)
|
||||||
|
self.create_background()
|
||||||
|
|
||||||
|
tk.Label(
|
||||||
|
self.root, text="Выберите собаку", font=("Comic Sans MS", 24), bg="#E5E5E5"
|
||||||
|
).pack(pady=20)
|
||||||
|
|
||||||
|
dog_frame = tk.Frame(self.root, bg="#E5E5E5")
|
||||||
|
dog_frame.pack(pady=50)
|
||||||
|
|
||||||
|
dog_size = 150
|
||||||
|
for breed, details in DOG_CHARACTERS.items():
|
||||||
|
try:
|
||||||
|
dog_image = Image.open(details["image"]).resize((dog_size, dog_size), Image.Resampling.LANCZOS)
|
||||||
|
dog_photo = ImageTk.PhotoImage(dog_image)
|
||||||
|
|
||||||
|
dog_container = tk.Frame(dog_frame, bg="#E5E5E5")
|
||||||
|
dog_container.pack(side=tk.LEFT, padx=15)
|
||||||
|
|
||||||
|
button = tk.Button(
|
||||||
|
dog_container,
|
||||||
|
image=dog_photo,
|
||||||
|
command=lambda b=breed: self.confirm_dog_selection(b),
|
||||||
|
bg="#E5E5E5",
|
||||||
|
borderwidth=0,
|
||||||
|
)
|
||||||
|
button.image = dog_photo
|
||||||
|
button.pack()
|
||||||
|
|
||||||
|
tk.Label(dog_container, text=breed, font=("Comic Sans MS", 14), bg="#E5E5E5").pack()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Ошибка загрузки изображения для собаки {breed}: {e}")
|
||||||
|
|
||||||
|
tk.Button(
|
||||||
|
self.root,
|
||||||
|
text="Вернуться",
|
||||||
|
font=("Comic Sans MS", 16),
|
||||||
|
bg="lightgreen",
|
||||||
|
command=self.return_to_main_menu_callback,
|
||||||
|
).place(relx=0.5, rely=0.9, anchor=tk.CENTER)
|
||||||
|
|
||||||
|
def confirm_dog_selection(self, breed):
|
||||||
|
"""Подтверждение выбора собаки."""
|
||||||
|
self.selected_dog = breed
|
||||||
|
self.show_level_selection()
|
||||||
|
|
||||||
|
def show_level_selection(self):
|
||||||
|
"""Отображение выбора уровня."""
|
||||||
|
clear_frame(self.root)
|
||||||
|
self.create_background()
|
||||||
|
|
||||||
|
tk.Label(self.root, text="Выберите уровень", font=("Comic Sans MS", 24), bg="#E5E5E5").pack(pady=20)
|
||||||
|
|
||||||
|
self.level_frame = tk.Frame(self.root, bg="#E5E5E5")
|
||||||
|
self.level_frame.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
|
||||||
|
|
||||||
|
progress = get_user_progress(self.user_id)
|
||||||
|
self.completed_levels = {session.level for session in progress if session.score > 0}
|
||||||
|
self.max_unlocked_level = max(self.completed_levels) + 1 if self.completed_levels else 1
|
||||||
|
|
||||||
|
for level in range(1, 101):
|
||||||
|
color = (
|
||||||
|
"#4CAF50" if level in self.completed_levels else
|
||||||
|
"#FFEB3B" if level == self.max_unlocked_level else
|
||||||
|
"#A9A9A9"
|
||||||
|
)
|
||||||
|
state = tk.NORMAL if level <= self.max_unlocked_level else tk.DISABLED
|
||||||
|
|
||||||
|
button = tk.Button(
|
||||||
|
self.level_frame,
|
||||||
|
text=f"Уровень {level}",
|
||||||
|
bg=color,
|
||||||
|
state=state,
|
||||||
|
font=("Comic Sans MS", 14),
|
||||||
|
command=lambda l=level: self.handle_level_selection(l)
|
||||||
|
)
|
||||||
|
button.grid(row=(level - 1) // 10, column=(level - 1) % 10, padx=5, pady=5)
|
||||||
|
|
||||||
|
self.update_level_buttons() # Обновляем кнопки уровней
|
||||||
|
|
||||||
|
tk.Button(
|
||||||
|
self.root,
|
||||||
|
text="Вернуться",
|
||||||
|
font=("Comic Sans MS", 16),
|
||||||
|
bg="lightgreen",
|
||||||
|
command=self.show_dog_selection
|
||||||
|
).place(relx=0.5, rely=0.9, anchor=tk.CENTER)
|
||||||
|
|
||||||
|
def handle_level_selection(self, level):
|
||||||
|
"""Обработка выбора уровня."""
|
||||||
|
if level in self.completed_levels:
|
||||||
|
if messagebox.askyesno("Повторить уровень", f"Вы уже прошли уровень {level}. Хотите пройти его заново?"):
|
||||||
|
self.is_replay = True
|
||||||
|
self.current_level = level
|
||||||
|
self.countdown() # Обратный отсчёт перед началом уровня
|
||||||
|
elif level <= self.max_unlocked_level:
|
||||||
|
self.current_level = level
|
||||||
|
self.is_replay = False
|
||||||
|
self.countdown() # Запуск обратного отсчёта перед началом игры
|
||||||
|
else:
|
||||||
|
messagebox.showinfo("Недоступно", "Пройдите предыдущие уровни, чтобы разблокировать этот.")
|
||||||
|
|
||||||
|
def update_level_buttons(self):
|
||||||
|
"""Обновление цветов и состояния кнопок уровней."""
|
||||||
|
if not hasattr(self, 'level_frame') or not self.level_frame.winfo_exists():
|
||||||
|
return
|
||||||
|
|
||||||
|
for widget in self.level_frame.winfo_children():
|
||||||
|
if isinstance(widget, tk.Button):
|
||||||
|
level = int(widget['text'].split()[-1]) # Получаем номер уровня из текста кнопки
|
||||||
|
# Определяем цвет и состояние кнопки
|
||||||
|
if level in self.completed_levels:
|
||||||
|
color = "#4CAF50" # Зелёный - завершённый уровень
|
||||||
|
state = tk.NORMAL
|
||||||
|
elif level == self.max_unlocked_level:
|
||||||
|
color = "#FFEB3B" # Жёлтый - текущий открытый уровень
|
||||||
|
state = tk.NORMAL
|
||||||
|
else:
|
||||||
|
color = "#A9A9A9" # Серый - заблокированный уровень
|
||||||
|
state = tk.DISABLED
|
||||||
|
|
||||||
|
widget.config(bg=color, state=state)
|
||||||
|
|
||||||
|
def start_level(self, level):
|
||||||
|
"""Запуск уровня."""
|
||||||
|
if level in self.completed_levels:
|
||||||
|
if messagebox.askyesno("Повторить уровень", f"Вы уже прошли уровень {level}. Хотите пройти его заново?"):
|
||||||
|
self.current_level = level
|
||||||
|
self.total_bones = 0
|
||||||
|
self.steps_taken = 0
|
||||||
|
self.start_game() # Запускаем уровень заново
|
||||||
|
return
|
||||||
|
elif level <= self.max_unlocked_level:
|
||||||
|
self.current_level = level
|
||||||
|
self.countdown() # Запуск обратного отсчёта перед началом игры
|
||||||
|
else:
|
||||||
|
messagebox.showinfo("Недоступно", "Этот уровень заблокирован.")
|
||||||
|
|
||||||
|
def countdown(self):
|
||||||
|
"""Обратный отсчёт перед началом уровня с анимацией."""
|
||||||
|
clear_frame(self.root) # Очищаем экран
|
||||||
|
countdown_label = tk.Label(
|
||||||
|
self.root, text="Готовьтесь!", font=("Comic Sans MS", 40), bg="#E5E5E5"
|
||||||
|
)
|
||||||
|
countdown_label.pack(expand=True)
|
||||||
|
|
||||||
|
def update_countdown(counter):
|
||||||
|
if counter > 0:
|
||||||
|
countdown_label.config(text=f"{counter}", fg=random.choice(["red", "green", "blue"]))
|
||||||
|
self.root.update()
|
||||||
|
self.root.after(1000, update_countdown, counter - 1)
|
||||||
|
else:
|
||||||
|
countdown_label.config(text="Вперёд!", fg="orange")
|
||||||
|
self.root.update()
|
||||||
|
self.root.after(1000, lambda: self.start_game(is_replay=self.is_replay))
|
||||||
|
|
||||||
|
update_countdown(3) # Старт обратного отсчёта с 3 секунд
|
||||||
|
|
||||||
|
def start_game(self, is_replay=False):
|
||||||
|
"""Запуск игрового процесса."""
|
||||||
|
self.is_replay = is_replay
|
||||||
|
logging.info(f"Игра начата на уровне {self.current_level}, повторное прохождение: {self.is_replay}")
|
||||||
|
clear_frame(self.root)
|
||||||
|
self.map_canvas = tk.Canvas(self.root, width=1920, height=1080, bg="#E5E5E5")
|
||||||
|
self.map_canvas.pack()
|
||||||
|
|
||||||
|
self.draw_grid()
|
||||||
|
|
||||||
|
# Сбрасываем состояние уровня
|
||||||
|
self.total_bones = 0
|
||||||
|
self.steps_taken = 0
|
||||||
|
self.dog_position = [1, 1]
|
||||||
|
|
||||||
|
# Генерация косточек, идентично первому запуску
|
||||||
|
self.bones_positions = self.generate_bones()
|
||||||
|
|
||||||
|
# Обновление интерфейса
|
||||||
|
self.rect_x1, self.rect_y1 = 1600, 0
|
||||||
|
self.rect_x2, self.rect_y2 = self.rect_x1 + 180, 100
|
||||||
|
self.map_canvas.create_rectangle(
|
||||||
|
self.rect_x1, self.rect_y1, self.rect_x2, self.rect_y2, fill="#CCCCCC", outline="#CCCCCC", tags="rect"
|
||||||
|
)
|
||||||
|
self.map_canvas.create_image(1650, 50, image=self.bones_photo, tags="rect")
|
||||||
|
self.bones_label = tk.Label(self.root, text=f"{self.total_bones}", font=("Comic Sans MS", 16), bg="#CCCCCC")
|
||||||
|
self.bones_label.place(x=1700, y=30)
|
||||||
|
|
||||||
|
self.update_map()
|
||||||
|
|
||||||
|
def draw_grid(self):
|
||||||
|
"""Рисует сетку для движения."""
|
||||||
|
for x in range(0, 1920, self.grid_size):
|
||||||
|
self.map_canvas.create_line(x, 0, x, 1080, fill="lightgray")
|
||||||
|
for y in range(0, 1080, self.grid_size):
|
||||||
|
self.map_canvas.create_line(0, y, 1920, y, fill="lightgray")
|
||||||
|
|
||||||
|
def generate_bones(self):
|
||||||
|
"""Генерация косточек на карте."""
|
||||||
|
bones_count = min(self.max_bones_per_level,
|
||||||
|
10 * (2 ** (self.current_level - 1))) # Ограничиваем количество косточек
|
||||||
|
bones = set() # Используем set для предотвращения дублирования косточек
|
||||||
|
|
||||||
|
while len(bones) < bones_count:
|
||||||
|
x = random.randint(0, self.cols - 1)
|
||||||
|
y = random.randint(0, self.rows - 1)
|
||||||
|
if (x, y) != tuple(self.dog_position): # Исключаем начальную позицию собаки
|
||||||
|
bones.add((x, y)) # Добавляем уникальную координату
|
||||||
|
|
||||||
|
logging.info(f"Сгенерировано косточек: {bones}")
|
||||||
|
return list(bones) # Преобразуем в список для дальнейшей обработки
|
||||||
|
|
||||||
|
def collect_bones(self):
|
||||||
|
"""Проверка и сбор косточек."""
|
||||||
|
for bone in self.bones_positions[:]:
|
||||||
|
if self.dog_position == [bone[0], bone[1]]:
|
||||||
|
self.bones_positions.remove(bone)
|
||||||
|
self.total_bones += 1
|
||||||
|
|
||||||
|
# Сохраняем прогресс только при первом прохождении
|
||||||
|
if not self.is_replay:
|
||||||
|
save_game_session(
|
||||||
|
user_id=self.user_id,
|
||||||
|
level=self.current_level,
|
||||||
|
score=self.total_bones,
|
||||||
|
duration=self.steps_taken,
|
||||||
|
steps=self.steps_taken,
|
||||||
|
health=100,
|
||||||
|
hunger=0,
|
||||||
|
sleepiness=0
|
||||||
|
)
|
||||||
|
|
||||||
|
self.bones_label.config(text=f"{self.total_bones}")
|
||||||
|
|
||||||
|
# Проверка на завершение уровня
|
||||||
|
target_bones = 10 * (2 ** (self.current_level - 1)) # Целевое количество косточек
|
||||||
|
if self.total_bones >= target_bones and not self.is_victory_screen_open:
|
||||||
|
if not self.is_replay:
|
||||||
|
self.show_victory_screen()
|
||||||
|
else:
|
||||||
|
self.start_game(is_replay=True)
|
||||||
|
|
||||||
|
# Генерация новых косточек каждые 10 шагов
|
||||||
|
if self.steps_taken % 10 == 0 and len(self.bones_positions) < self.max_bones_per_level:
|
||||||
|
new_bones = self.generate_bones()
|
||||||
|
for bone in new_bones:
|
||||||
|
if bone not in self.bones_positions:
|
||||||
|
self.bones_positions.append(bone) # Добавляем только уникальные косточки
|
||||||
|
logging.info(f"Добавлены косточки: {new_bones}")
|
||||||
|
|
||||||
|
def move_up(self, event):
|
||||||
|
"""Движение вверх."""
|
||||||
|
self.root.focus_force()
|
||||||
|
if self.dog_position[1] > 0:
|
||||||
|
self.dog_position[1] -= 1
|
||||||
|
self.steps_taken += 1
|
||||||
|
self.update_map()
|
||||||
|
|
||||||
|
def move_down(self, event):
|
||||||
|
"""Движение вниз."""
|
||||||
|
self.root.focus_force()
|
||||||
|
if self.dog_position[1] < self.rows - 1:
|
||||||
|
self.dog_position[1] += 1
|
||||||
|
self.steps_taken += 1
|
||||||
|
self.update_map()
|
||||||
|
|
||||||
|
def move_left(self, event):
|
||||||
|
"""Движение влево."""
|
||||||
|
self.root.focus_force()
|
||||||
|
if self.dog_position[0] > 0:
|
||||||
|
self.dog_position[0] -= 1
|
||||||
|
self.steps_taken += 1
|
||||||
|
self.update_map()
|
||||||
|
|
||||||
|
def move_right(self, event):
|
||||||
|
"""Движение вправо."""
|
||||||
|
self.root.focus_force()
|
||||||
|
if self.dog_position[0] < self.cols - 1:
|
||||||
|
self.dog_position[0] += 1
|
||||||
|
self.steps_taken += 1
|
||||||
|
self.update_map()
|
||||||
|
|
||||||
|
def on_escape(self, event):
|
||||||
|
"""Обработчик для клавиши ESC."""
|
||||||
|
if self.map_canvas: # Проверяем, что игрок находится на карте
|
||||||
|
if self.is_pause_menu_open:
|
||||||
|
self.resume_game() # Закрываем окно паузы и продолжаем игру
|
||||||
|
else:
|
||||||
|
self.show_pause_menu() # Открываем окно паузы
|
||||||
|
|
||||||
|
def show_pause_menu(self):
|
||||||
|
"""Создание окна паузы."""
|
||||||
|
if self.is_pause_menu_open:
|
||||||
|
return # Если окно паузы уже открыто, ничего не делаем
|
||||||
|
|
||||||
|
self.is_pause_menu_open = True # Устанавливаем флаг
|
||||||
|
|
||||||
|
self.pause_window = tk.Toplevel(self.root)
|
||||||
|
self.pause_window.title("Пауза")
|
||||||
|
self.pause_window.geometry("400x200")
|
||||||
|
self.pause_window.configure(bg="#E5E5E5")
|
||||||
|
self.pause_window.grab_set() # Блокируем взаимодействие с основным окном
|
||||||
|
|
||||||
|
# Кнопка "Сохранить и выйти"
|
||||||
|
save_exit_button = tk.Button(
|
||||||
|
self.pause_window,
|
||||||
|
text="Сохранить и выйти",
|
||||||
|
font=("Comic Sans MS", 16),
|
||||||
|
bg="#FF6347",
|
||||||
|
command=self.save_and_exit
|
||||||
|
)
|
||||||
|
save_exit_button.pack(pady=20)
|
||||||
|
|
||||||
|
# Кнопка "Продолжить"
|
||||||
|
continue_button = tk.Button(
|
||||||
|
self.pause_window,
|
||||||
|
text="Продолжить",
|
||||||
|
font=("Comic Sans MS", 16),
|
||||||
|
bg="#4CAF50",
|
||||||
|
command=self.resume_game
|
||||||
|
)
|
||||||
|
continue_button.pack(pady=20)
|
||||||
|
|
||||||
|
def resume_game(self):
|
||||||
|
"""Закрытие окна паузы и продолжение игры."""
|
||||||
|
if self.is_pause_menu_open:
|
||||||
|
self.pause_window.destroy() # Закрываем окно паузы
|
||||||
|
self.is_pause_menu_open = False # Сбрасываем флаг
|
||||||
|
self.is_game_active = True # Возвращаем игру в активное состояние
|
||||||
|
|
||||||
|
def save_and_exit(self):
|
||||||
|
"""Сохранение данных и выход в главное меню."""
|
||||||
|
logging.info("Сохранение прогресса: уровень %d, собрано косточек %d.", self.current_level, self.total_bones)
|
||||||
|
# Дополнительно можно добавить сохранение прогресса в базу данных.
|
||||||
|
# Пример:
|
||||||
|
# save_progress_to_database(user_id=self.user_id, level=self.current_level, bones=self.total_bones)
|
||||||
|
self.return_to_main_menu_callback() # Возврат в главное меню
|
||||||
|
|
||||||
|
def update_map(self):
|
||||||
|
"""Обновление карты."""
|
||||||
|
if self.is_victory_screen_open: # Отключаем обновления, если окно победы открыто
|
||||||
|
return
|
||||||
|
|
||||||
|
self.map_canvas.delete("all") # Удаляем старые объекты карты
|
||||||
|
self.draw_grid() # Перерисовываем сетку
|
||||||
|
|
||||||
|
# Отображение косточек
|
||||||
|
for x, y in self.bones_positions:
|
||||||
|
self.map_canvas.create_image(
|
||||||
|
x * self.grid_size + self.grid_size // 2,
|
||||||
|
y * self.grid_size + self.grid_size // 2,
|
||||||
|
image=self.bones_photo
|
||||||
|
)
|
||||||
|
|
||||||
|
# Отображение собаки
|
||||||
|
if self.selected_dog:
|
||||||
|
dog_image = Image.open(DOG_CHARACTERS[self.selected_dog]["image"]).resize(
|
||||||
|
(self.grid_size, self.grid_size),
|
||||||
|
Image.Resampling.LANCZOS
|
||||||
|
)
|
||||||
|
self.dog_photo = ImageTk.PhotoImage(dog_image)
|
||||||
|
self.map_canvas.create_image(
|
||||||
|
self.dog_position[0] * self.grid_size + self.grid_size // 2,
|
||||||
|
self.dog_position[1] * self.grid_size + self.grid_size // 2,
|
||||||
|
image=self.dog_photo
|
||||||
|
)
|
||||||
|
|
||||||
|
# Проверка сбора косточек
|
||||||
|
self.collect_bones()
|
||||||
|
|
||||||
|
# Условие перехода на следующий уровень
|
||||||
|
target_bones = 10 * (2 ** (self.current_level - 1)) # Геометрическая прогрессия
|
||||||
|
if self.total_bones >= target_bones and not self.is_victory_screen_open:
|
||||||
|
self.show_victory_screen()
|
||||||
|
|
||||||
|
def show_victory_screen(self):
|
||||||
|
"""Экран победы."""
|
||||||
|
if self.is_victory_screen_open:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.is_victory_screen_open = True
|
||||||
|
self.is_game_active = False
|
||||||
|
|
||||||
|
if not self.is_replay:
|
||||||
|
# Сохранение прогресса при первом прохождении
|
||||||
|
save_game_session(
|
||||||
|
user_id=self.user_id,
|
||||||
|
level=self.current_level,
|
||||||
|
score=self.total_bones,
|
||||||
|
duration=self.steps_taken,
|
||||||
|
steps=self.steps_taken,
|
||||||
|
health=100,
|
||||||
|
hunger=0,
|
||||||
|
sleepiness=0
|
||||||
|
)
|
||||||
|
self.completed_levels.add(self.current_level)
|
||||||
|
self.max_unlocked_level = max(self.max_unlocked_level, self.current_level + 1)
|
||||||
|
|
||||||
|
self.update_level_buttons()
|
||||||
|
|
||||||
|
# Открываем окно победы
|
||||||
|
victory_window = tk.Toplevel(self.root)
|
||||||
|
victory_window.title("Уровень завершён!")
|
||||||
|
victory_window.geometry("800x400")
|
||||||
|
victory_window.configure(bg="#E5E5E5")
|
||||||
|
victory_window.grab_set()
|
||||||
|
|
||||||
|
# Текст победы
|
||||||
|
victory_label = tk.Label(victory_window, text=f"Поздравляем! Уровень {self.current_level} завершён!",
|
||||||
|
font=("Comic Sans MS", 24), bg="#E5E5E5")
|
||||||
|
victory_label.place(x=200, y=20) # Устанавливаем верхнюю позицию текста победы
|
||||||
|
|
||||||
|
# Изображение собаки
|
||||||
|
dog_image = Image.open(DOG_CHARACTERS[self.selected_dog]["image"]).resize((200, 200), Image.Resampling.LANCZOS)
|
||||||
|
dog_photo = ImageTk.PhotoImage(dog_image)
|
||||||
|
dog_label = tk.Label(victory_window, image=dog_photo, bg="#E5E5E5")
|
||||||
|
dog_label.image = dog_photo
|
||||||
|
dog_label.place(x=50, y=120) # Сдвигаем изображение собаки вниз
|
||||||
|
|
||||||
|
# Характеристики собаки
|
||||||
|
dog_info = f"Порода: {self.selected_dog}"
|
||||||
|
info_label = tk.Label(victory_window, text=dog_info, font=("Comic Sans MS", 16), bg="#E5E5E5")
|
||||||
|
info_label.place(x=300, y=120) # Размещаем характеристики собаки ниже текста победы и изображения собаки
|
||||||
|
|
||||||
|
# Собрано косточек
|
||||||
|
target_bones = 10 * (2 ** (self.current_level - 1)) # Геометрическая прогрессия
|
||||||
|
collected_info = f"Собрано: {self.total_bones} из {target_bones}"
|
||||||
|
score_label = tk.Label(victory_window, text=collected_info, font=("Comic Sans MS", 16), bg="#E5E5E5")
|
||||||
|
score_label.place(x=300, y=170) # Размещаем информацию о собранных косточках ниже характеристик собаки
|
||||||
|
|
||||||
|
# Никнейм игрока
|
||||||
|
user_info = get_user_by_id(self.user_id)
|
||||||
|
username_label = tk.Label(victory_window, text=f"Никнейм: {user_info.username}", font=("Comic Sans MS", 16),
|
||||||
|
bg="#E5E5E5")
|
||||||
|
username_label.place(x=300, y=220) # Размещаем никнейм игрока ниже собранных косточек
|
||||||
|
|
||||||
|
# Кнопки управления
|
||||||
|
button_frame = tk.Frame(victory_window, bg="#E5E5E5")
|
||||||
|
button_frame.pack(side=tk.BOTTOM, pady=20)
|
||||||
|
|
||||||
|
next_level_button = tk.Button(
|
||||||
|
button_frame,
|
||||||
|
text="Следующий уровень",
|
||||||
|
font=("Comic Sans MS", 14),
|
||||||
|
bg="#4CAF50",
|
||||||
|
command=lambda: [victory_window.destroy(), self.start_next_level()]
|
||||||
|
)
|
||||||
|
next_level_button.pack(side=tk.LEFT, padx=10)
|
||||||
|
|
||||||
|
"""
|
||||||
|
replay_button = tk.Button(
|
||||||
|
button_frame,
|
||||||
|
text="Пройти уровень снова",
|
||||||
|
font=("Comic Sans MS", 14),
|
||||||
|
bg="#FFEB3B",
|
||||||
|
command=lambda: [victory_window.destroy(), self.start_game(is_replay=True)] # Перезапуск уровня
|
||||||
|
)
|
||||||
|
replay_button.pack(side=tk.LEFT, padx=10)
|
||||||
|
"""
|
||||||
|
|
||||||
|
exit_button = tk.Button(
|
||||||
|
button_frame,
|
||||||
|
text="Выйти в главное меню",
|
||||||
|
font=("Comic Sans MS", 14),
|
||||||
|
bg="#FF6347",
|
||||||
|
command=lambda: [victory_window.destroy(), self.return_to_main_menu()]
|
||||||
|
)
|
||||||
|
exit_button.pack(side=tk.LEFT, padx=10)
|
||||||
|
|
||||||
|
def close_victory_window(self):
|
||||||
|
"""Закрытие окна победы и сброс флага."""
|
||||||
|
self.is_victory_screen_open = False
|
||||||
|
self.is_game_active = True
|
||||||
|
self.return_to_main_menu() # Возвращаем в меню
|
||||||
|
|
||||||
|
def return_to_main_menu(self):
|
||||||
|
"""Возврат в главное меню."""
|
||||||
|
if self.is_pause_menu_open:
|
||||||
|
self.pause_window.destroy() # Закрываем окно паузы
|
||||||
|
self.is_pause_menu_open = False # Сбрасываем флаг
|
||||||
|
|
||||||
|
clear_frame(self.root) # Очищаем текущий экран
|
||||||
|
self.show_main_menu() # Переходим в главное меню
|
||||||
|
|
||||||
|
def start_next_level(self):
|
||||||
|
"""Запуск следующего уровня."""
|
||||||
|
self.current_level += 1 # Переход на следующий уровень
|
||||||
|
self.total_bones = 0 # Сброс собранных косточек
|
||||||
|
self.steps_taken = 0 # Сброс количества шагов
|
||||||
|
self.dog_position = [1, 1] # Возвращаем собаку в начальную позицию
|
||||||
|
self.bones_positions = [] # Очищаем косточки
|
||||||
|
self.is_victory_screen_open = False # Закрываем экран победы, если он был открыт
|
||||||
|
|
||||||
|
# Сохраняем новый прогресс в базу данных
|
||||||
|
save_game_session(
|
||||||
|
user_id=self.user_id,
|
||||||
|
level=self.current_level,
|
||||||
|
score=0,
|
||||||
|
duration=0,
|
||||||
|
steps=0,
|
||||||
|
health=100,
|
||||||
|
hunger=0,
|
||||||
|
sleepiness=0
|
||||||
|
)
|
||||||
|
logging.info(f"Запуск уровня {self.current_level}.")
|
||||||
|
self.countdown() # Запускаем обратный отсчёт перед началом уровня
|
||||||
|
|
||||||
|
def save_progress(self):
|
||||||
|
"""Сохранение игрового процесса в таблицу GameSessions."""
|
||||||
|
if not self.user_id:
|
||||||
|
logging.error("Ошибка: user_id равен None. Запись невозможна.")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Рассчитываем длительность уровня и текущий счет
|
||||||
|
duration = self.steps_taken
|
||||||
|
score = self.total_bones
|
||||||
|
|
||||||
|
# Логирование
|
||||||
|
logging.info(
|
||||||
|
f"Сохранение сессии: user_id={self.user_id}, level={self.current_level}, score={score}, duration={duration}")
|
||||||
|
|
||||||
|
# Сохранение данных в базу
|
||||||
|
save_game_session(
|
||||||
|
user_id=self.user_id,
|
||||||
|
level=self.current_level,
|
||||||
|
score=self.total_bones,
|
||||||
|
steps=self.steps_taken, # Используйте количество шагов или время
|
||||||
|
duration=self.steps_taken, # Если 'steps' отражают время, используйте их
|
||||||
|
health=100, # Примерное значение
|
||||||
|
hunger=0, # Примерное значение
|
||||||
|
sleepiness=0 # Примерное значение
|
||||||
|
)
|
||||||
|
|
||||||
|
logging.info("Прогресс успешно сохранен.")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Ошибка при сохранении прогресса: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
def create_main_menu_button(self):
|
||||||
|
"""Создаём кнопку для возврата в главное меню."""
|
||||||
|
main_menu_button = tk.Button(
|
||||||
|
self.root,
|
||||||
|
text="Главное меню",
|
||||||
|
font=("Comic Sans MS", 16),
|
||||||
|
bg="lightgreen",
|
||||||
|
command=self.show_main_menu, # Вызов нового метода
|
||||||
|
)
|
||||||
|
main_menu_button.pack()
|
||||||
|
|
||||||
|
def show_main_menu(self):
|
||||||
|
"""Переход в главное меню."""
|
||||||
|
self.is_game_active = False # Останавливаем игру, если мы возвращаемся в меню
|
||||||
|
clear_frame(self.root) # Очищаем текущий экран
|
||||||
|
self.return_to_main_menu_callback() # Вызов колбэка для возврата в главное меню
|
||||||
107
src/ui/user_ui/knowledge_ui.py
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
import os
|
||||||
|
import tkinter as tk
|
||||||
|
from PIL import Image, ImageTk
|
||||||
|
from config import DOG_CHARACTERS, BASE_DIR
|
||||||
|
from src.utils import clear_frame
|
||||||
|
from database.info.Dogs_table import get_all_dogs
|
||||||
|
|
||||||
|
|
||||||
|
def knowledge_ui(root, user_app):
|
||||||
|
"""Интерфейс базы знаний о породах собак."""
|
||||||
|
clear_frame(root)
|
||||||
|
|
||||||
|
# Загружаем данные о породах собак из базы данных
|
||||||
|
dog_data = get_all_dogs()
|
||||||
|
if not dog_data:
|
||||||
|
tk.Label(root, text="Не удалось загрузить данные о породах.", font=("Arial", 20)).pack()
|
||||||
|
return
|
||||||
|
|
||||||
|
index = {"current": 0} # Индекс текущей породы
|
||||||
|
|
||||||
|
def update_content():
|
||||||
|
"""Обновляет содержимое для текущей породы."""
|
||||||
|
current_dog = dog_data[index["current"]]
|
||||||
|
breed = current_dog.breed
|
||||||
|
|
||||||
|
# Загружаем информацию из DOG_CHARACTERS
|
||||||
|
dog_info = DOG_CHARACTERS.get(breed)
|
||||||
|
if not dog_info:
|
||||||
|
title_label.config(text="Нет данных о породе.")
|
||||||
|
image_label.config(image=None)
|
||||||
|
image_label.image = None
|
||||||
|
characteristics_label.config(text="")
|
||||||
|
behavior_label.config(text="")
|
||||||
|
care_label.config(text="")
|
||||||
|
admin_comments_label.config(text="")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Загружаем изображение
|
||||||
|
image_path = dog_info["image"]
|
||||||
|
if os.path.exists(image_path):
|
||||||
|
image = Image.open(image_path)
|
||||||
|
image = image.resize((200, 200), Image.Resampling.LANCZOS)
|
||||||
|
photo = ImageTk.PhotoImage(image)
|
||||||
|
image_label.config(image=photo)
|
||||||
|
image_label.image = photo
|
||||||
|
else:
|
||||||
|
image_label.config(image=None)
|
||||||
|
image_label.image = None
|
||||||
|
|
||||||
|
# Обновляем текст
|
||||||
|
title_label.config(text=breed)
|
||||||
|
characteristics_label.config(text=f"Характеристики: {current_dog.characteristics}")
|
||||||
|
behavior_label.config(text=f"Поведение: {current_dog.behavior}")
|
||||||
|
care_label.config(text=f"Уход: {current_dog.care_info}")
|
||||||
|
admin_comments_label.config(text=f"Комментарии: {current_dog.admin_comments}")
|
||||||
|
|
||||||
|
def next_breed():
|
||||||
|
"""Переход к следующей породе."""
|
||||||
|
index["current"] = (index["current"] + 1) % len(dog_data)
|
||||||
|
update_content()
|
||||||
|
|
||||||
|
def previous_breed():
|
||||||
|
"""Переход к предыдущей породе."""
|
||||||
|
index["current"] = (index["current"] - 1) % len(dog_data)
|
||||||
|
update_content()
|
||||||
|
|
||||||
|
# Основной интерфейс
|
||||||
|
frame = tk.Frame(root, bg="#f0f0f0")
|
||||||
|
frame.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
title_label = tk.Label(frame, text="", font=("Arial", 20), bg="#f0f0f0")
|
||||||
|
title_label.pack(pady=10)
|
||||||
|
|
||||||
|
image_label = tk.Label(frame, bg="#f0f0f0")
|
||||||
|
image_label.pack(pady=10)
|
||||||
|
|
||||||
|
characteristics_label = tk.Label(frame, text="", font=("Arial", 14), bg="#f0f0f0", wraplength=600)
|
||||||
|
characteristics_label.pack(pady=5)
|
||||||
|
|
||||||
|
behavior_label = tk.Label(frame, text="", font=("Arial", 14), bg="#f0f0f0", wraplength=600)
|
||||||
|
behavior_label.pack(pady=5)
|
||||||
|
|
||||||
|
care_label = tk.Label(frame, text="", font=("Arial", 14), bg="#f0f0f0", wraplength=600)
|
||||||
|
care_label.pack(pady=5)
|
||||||
|
|
||||||
|
admin_comments_label = tk.Label(frame, text="", font=("Arial", 14), bg="#f0f0f0", wraplength=600)
|
||||||
|
admin_comments_label.pack(pady=5)
|
||||||
|
|
||||||
|
# Кнопки навигации
|
||||||
|
btn_frame = tk.Frame(frame, bg="#f0f0f0")
|
||||||
|
btn_frame.pack(pady=20)
|
||||||
|
|
||||||
|
back_button = tk.Button(
|
||||||
|
btn_frame,
|
||||||
|
text="Назад",
|
||||||
|
font=("Arial", 14),
|
||||||
|
command=lambda: [clear_frame(root), user_app.show_user_dashboard()]
|
||||||
|
)
|
||||||
|
back_button.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
prev_button = tk.Button(btn_frame, text="Предыдущая", font=("Arial", 14), command=previous_breed)
|
||||||
|
prev_button.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
next_button = tk.Button(btn_frame, text="Следующая", font=("Arial", 14), command=next_breed)
|
||||||
|
next_button.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
update_content() # Инициализация первого отображения
|
||||||
182
src/ui/user_ui/main_menu.py
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
import logging
|
||||||
|
import tkinter as tk
|
||||||
|
from functools import partial
|
||||||
|
from tkinter import messagebox, Canvas
|
||||||
|
from PIL import Image, ImageTk
|
||||||
|
import math
|
||||||
|
|
||||||
|
from config import BUTTON_COLOR_EXIT, CHIHUAHUA, CORGI, RETRIEVER, HUSKY, POMERANIAN, PUG, YORKSHIRE
|
||||||
|
from src.ui.user_ui.game_ui import GameUI
|
||||||
|
from src.ui.user_ui.knowledge_ui import knowledge_ui
|
||||||
|
from src.ui.user_ui.profile_ui import profile_ui
|
||||||
|
|
||||||
|
# Пути к изображениям собак
|
||||||
|
DOG_IMAGES = [
|
||||||
|
CHIHUAHUA,
|
||||||
|
CORGI,
|
||||||
|
RETRIEVER,
|
||||||
|
HUSKY,
|
||||||
|
POMERANIAN,
|
||||||
|
PUG,
|
||||||
|
YORKSHIRE
|
||||||
|
]
|
||||||
|
|
||||||
|
# Настройки
|
||||||
|
BACKGROUND_COLOR = "#E5E5E5" # Цвет фона
|
||||||
|
BUTTON_COLOR_PLAY = "#4CAF50" # Цвет кнопки играть
|
||||||
|
BUTTON_TEXT_COLOR = "white" # Цвет текста на кнопке
|
||||||
|
FONT = ("Arial", 12)
|
||||||
|
BIG_FONT = ("Arial", 24)
|
||||||
|
PLAY_BUTTON_RADIUS = 100 # Радиус кнопки "Играть"
|
||||||
|
|
||||||
|
|
||||||
|
class UserApp:
|
||||||
|
def __init__(self, root, user_id):
|
||||||
|
"""Инициализация пользовательского интерфейса."""
|
||||||
|
self.root = root
|
||||||
|
self.user_id = user_id
|
||||||
|
self.root.configure(bg="#E5E5E5")
|
||||||
|
self.root.geometry("1920x1080")
|
||||||
|
self.root.title("Собачья академия")
|
||||||
|
self.show_user_dashboard()
|
||||||
|
|
||||||
|
def show_user_dashboard(self):
|
||||||
|
"""Показать интерфейс пользователя."""
|
||||||
|
center_x, center_y = 960, 540 # Центр экрана
|
||||||
|
radius = 300 # Радиус круга для размещения собак
|
||||||
|
num_dogs = len(DOG_IMAGES)
|
||||||
|
|
||||||
|
# Верхняя панель
|
||||||
|
top_panel = tk.Frame(self.root, bg="#333333", height=100)
|
||||||
|
top_panel.pack(fill=tk.X, side=tk.TOP)
|
||||||
|
|
||||||
|
# Кнопки на верхней панели
|
||||||
|
profile_button = tk.Button(
|
||||||
|
top_panel,
|
||||||
|
text="Профиль",
|
||||||
|
bg="#555555",
|
||||||
|
fg="white",
|
||||||
|
font=FONT,
|
||||||
|
relief=tk.FLAT,
|
||||||
|
padx=20,
|
||||||
|
pady=10,
|
||||||
|
command=self.show_profile
|
||||||
|
)
|
||||||
|
profile_button.pack(side=tk.LEFT, padx=20)
|
||||||
|
|
||||||
|
shop_button = tk.Button(
|
||||||
|
top_panel,
|
||||||
|
text="Магазин",
|
||||||
|
bg="#555555",
|
||||||
|
fg="white",
|
||||||
|
font=FONT,
|
||||||
|
relief=tk.FLAT,
|
||||||
|
padx=20,
|
||||||
|
pady=10,
|
||||||
|
state=tk.DISABLED # Делаем кнопку некликабельной
|
||||||
|
)
|
||||||
|
shop_button.pack(side=tk.LEFT, padx=20)
|
||||||
|
|
||||||
|
knowledge_button = tk.Button(
|
||||||
|
top_panel,
|
||||||
|
text="База знаний",
|
||||||
|
bg="#555555",
|
||||||
|
fg="white",
|
||||||
|
font=FONT,
|
||||||
|
relief=tk.FLAT,
|
||||||
|
padx=20,
|
||||||
|
pady=10,
|
||||||
|
state=tk.NORMAL, # Делаем кнопку активной
|
||||||
|
command=lambda: knowledge_ui(self.root, self) # Подключаем knowledge_ui
|
||||||
|
)
|
||||||
|
knowledge_button.pack(side=tk.LEFT, padx=20)
|
||||||
|
|
||||||
|
# Размещение собак по кругу
|
||||||
|
self.place_dog_images(center_x, center_y, radius, num_dogs)
|
||||||
|
|
||||||
|
# Кнопка "Играть" (увеличенная)
|
||||||
|
play_button_canvas = tk.Canvas(
|
||||||
|
self.root,
|
||||||
|
width=PLAY_BUTTON_RADIUS * 2,
|
||||||
|
height=PLAY_BUTTON_RADIUS * 2,
|
||||||
|
bg=BACKGROUND_COLOR,
|
||||||
|
highlightthickness=0,
|
||||||
|
)
|
||||||
|
play_button_canvas.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
|
||||||
|
|
||||||
|
play_button_canvas.create_oval(
|
||||||
|
0, 0, PLAY_BUTTON_RADIUS * 2, PLAY_BUTTON_RADIUS * 2,
|
||||||
|
fill=BUTTON_COLOR_PLAY,
|
||||||
|
outline=BUTTON_COLOR_PLAY,
|
||||||
|
)
|
||||||
|
play_button_canvas.create_text(
|
||||||
|
PLAY_BUTTON_RADIUS,
|
||||||
|
PLAY_BUTTON_RADIUS,
|
||||||
|
text="Играть",
|
||||||
|
fill=BUTTON_TEXT_COLOR,
|
||||||
|
font=BIG_FONT,
|
||||||
|
)
|
||||||
|
play_button_canvas.tag_bind("all", "<Button-1>", lambda e: self.play_game())
|
||||||
|
|
||||||
|
# Кнопка выхода
|
||||||
|
exit_button = tk.Button(
|
||||||
|
self.root,
|
||||||
|
text="Выйти",
|
||||||
|
bg=BUTTON_COLOR_EXIT,
|
||||||
|
fg="white",
|
||||||
|
font=FONT,
|
||||||
|
command=self.exit_app
|
||||||
|
)
|
||||||
|
exit_button.place(relx=0.9, rely=0.95, anchor=tk.CENTER)
|
||||||
|
|
||||||
|
def place_dog_images(self, center_x, center_y, radius, num_dogs):
|
||||||
|
"""Размещает изображения собак по кругу."""
|
||||||
|
angle_step = 2 * math.pi / num_dogs # Шаг угла для размещения собак
|
||||||
|
for i in range(num_dogs):
|
||||||
|
angle = i * angle_step
|
||||||
|
x = center_x + radius * math.cos(angle)
|
||||||
|
y = center_y + radius * math.sin(angle)
|
||||||
|
|
||||||
|
# Загрузка изображения собаки
|
||||||
|
image_path = DOG_IMAGES[i]
|
||||||
|
try:
|
||||||
|
dog_image = Image.open(image_path)
|
||||||
|
dog_image = dog_image.resize((100, 100), Image.Resampling.LANCZOS)
|
||||||
|
dog_photo = ImageTk.PhotoImage(dog_image)
|
||||||
|
|
||||||
|
# Создание метки с изображением
|
||||||
|
dog_label = tk.Label(self.root, image=dog_photo, bg=BACKGROUND_COLOR)
|
||||||
|
dog_label.image = dog_photo # Сохраняем ссылку на изображение
|
||||||
|
dog_label.place(x=x - 50, y=y - 50) # Центрируем метку относительно позиции
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Ошибка загрузки изображения {image_path}: {e}")
|
||||||
|
|
||||||
|
def show_profile(self):
|
||||||
|
"""Показать экран профиля пользователя."""
|
||||||
|
try:
|
||||||
|
self.clear_frame()
|
||||||
|
profile_ui(self.root, self.user_id, self)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Ошибка при отображении профиля: {e}")
|
||||||
|
messagebox.showerror("Ошибка", "Не удалось открыть профиль.")
|
||||||
|
|
||||||
|
def clear_frame(self):
|
||||||
|
"""Очистить текущий экран."""
|
||||||
|
for widget in self.root.winfo_children():
|
||||||
|
widget.destroy()
|
||||||
|
|
||||||
|
def play_game(self):
|
||||||
|
"""Запуск игры и передача колбэка для возврата в меню."""
|
||||||
|
# Передаем метод через partial для корректной передачи self
|
||||||
|
return_to_main_menu = partial(self.return_to_main_menu)
|
||||||
|
GameUI(self.root, self.user_id, return_to_main_menu)
|
||||||
|
|
||||||
|
def return_to_main_menu(self):
|
||||||
|
"""Возврат в главное меню."""
|
||||||
|
self.clear_frame() # Очищаем экран перед переходом
|
||||||
|
self.show_user_dashboard() # Показываем главное меню
|
||||||
|
|
||||||
|
def exit_app(self):
|
||||||
|
"""Подтверждение выхода из приложения."""
|
||||||
|
if messagebox.askyesno("Выход", "Вы уверены, что хотите выйти?"):
|
||||||
|
self.root.quit()
|
||||||
43
src/ui/user_ui/profile_ui.py
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from src.utils import clear_frame
|
||||||
|
from database.db_events import get_user_progress, get_user_by_id
|
||||||
|
|
||||||
|
|
||||||
|
def profile_ui(root, user_id, user_app):
|
||||||
|
"""Интерфейс профиля пользователя."""
|
||||||
|
clear_frame(root)
|
||||||
|
|
||||||
|
frame = tk.Frame(root, bg="#f8e1e1")
|
||||||
|
frame.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
# Обновляем данные пользователя из базы
|
||||||
|
user = get_user_by_id(user_id)
|
||||||
|
if not user:
|
||||||
|
username = "Неизвестный пользователь"
|
||||||
|
levels_completed = 0
|
||||||
|
bones_collected = 0
|
||||||
|
else:
|
||||||
|
username = user.username
|
||||||
|
progress = get_user_progress(user_id)
|
||||||
|
levels_completed = len({session.level for session in progress if session.score > 0})
|
||||||
|
bones_collected = sum(session.score for session in progress)
|
||||||
|
|
||||||
|
tk.Label(
|
||||||
|
frame,
|
||||||
|
text=f"Профиль: {username}",
|
||||||
|
font=("Comic Sans MS", 30),
|
||||||
|
bg="#f8e1e1",
|
||||||
|
).pack(pady=20)
|
||||||
|
|
||||||
|
stats_text = f"Пройдено уровней: {levels_completed}\nСобрано косточек: {bones_collected}"
|
||||||
|
tk.Label(frame, text=stats_text, font=("Comic Sans MS", 20), bg="#f8e1e1").pack(pady=10)
|
||||||
|
|
||||||
|
# Кнопка "Назад"
|
||||||
|
back_button = tk.Button(
|
||||||
|
frame,
|
||||||
|
text="Назад",
|
||||||
|
command=lambda: [clear_frame(root), user_app.show_user_dashboard()],
|
||||||
|
font=("Comic Sans MS", 20)
|
||||||
|
)
|
||||||
|
back_button.pack(pady=20)
|
||||||
|
|
||||||
BIN
src/user_functions/__pycache__/game_functions.cpython-313.pyc
Normal file
BIN
src/user_functions/__pycache__/game_logs.cpython-313.pyc
Normal file
BIN
src/user_functions/__pycache__/map_generator.cpython-313.pyc
Normal file
18
src/user_functions/game_logs.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
def setup_logging():
|
||||||
|
"""Настройка логирования в файл."""
|
||||||
|
log_dir = "logs"
|
||||||
|
if not os.path.exists(log_dir):
|
||||||
|
os.makedirs(log_dir) # Создание директории, если она не существует
|
||||||
|
|
||||||
|
log_file = os.path.join(log_dir, "game.log")
|
||||||
|
|
||||||
|
logging.basicConfig(
|
||||||
|
filename=log_file,
|
||||||
|
level=logging.DEBUG,
|
||||||
|
format="%(asctime)s - %(levelname)s - %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
logging.info("Логирование игры начато.")
|
||||||
28
src/utils.py
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import tkinter as tk
|
||||||
|
|
||||||
|
|
||||||
|
def clear_frame(frame):
|
||||||
|
"""Очистить все виджеты в frame"""
|
||||||
|
for widget in frame.winfo_children():
|
||||||
|
widget.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def feature_in_development_admin(frame):
|
||||||
|
"""Сообщение о том, что функционал недоступен."""
|
||||||
|
clear_frame(frame) # Очистка фрейма перед выводом сообщения
|
||||||
|
tk.Label(
|
||||||
|
frame,
|
||||||
|
text="Этот функционал пока что недоступен, в разработке.",
|
||||||
|
bg="#403d49", # Фон сообщения
|
||||||
|
fg="#b2acc0", # Цвет текста
|
||||||
|
font=("Comic Sans MS", 16)
|
||||||
|
).pack(expand=True)
|
||||||
|
|
||||||
|
|
||||||
|
def show_message(message):
|
||||||
|
"""Показать сообщение пользователю"""
|
||||||
|
message_window = tk.Toplevel()
|
||||||
|
message_label = tk.Label(message_window, text=message, font=("Comic Sans MS", 16))
|
||||||
|
message_label.pack(pady=20)
|
||||||
|
ok_button = tk.Button(message_window, text="OK", command=message_window.destroy)
|
||||||
|
ok_button.pack(pady=10)
|
||||||