Изменения:
1. Ошибка "WHERE game_sessions.user_id IS NULL" + игра получает user_id из бд после создания пользователя, авторизации 2. Провиль пользователя + отображается никнейм 3. Уровни + добавлена рамка с 100 уровнями + добавлена система смены цвета кнопки уровня в зависимости от состояния (пройден/не пройден) 4. Окно победы + добавлено отображение никнейма
This commit is contained in:
parent
9f5d36d1a1
commit
5d34162267
13 changed files with 5512 additions and 234 deletions
BIN
database/DogAcademy.db
Normal file
BIN
database/DogAcademy.db
Normal file
Binary file not shown.
|
|
@ -1,3 +1,4 @@
|
|||
import logging
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import joinedload
|
||||
from database.db_session import get_session
|
||||
|
|
@ -6,36 +7,50 @@ from sqlalchemy.exc import SQLAlchemyError
|
|||
|
||||
|
||||
def get_user_by_id(user_id):
|
||||
"""Получение данных пользователя по ID."""
|
||||
"""Получение данных пользователя по ID с предварительной загрузкой связанных данных."""
|
||||
session = get_session()
|
||||
try:
|
||||
user = session.query(Users).filter_by(user_id=user_id).first()
|
||||
user = (
|
||||
session.query(Users)
|
||||
.options(joinedload(Users.game_sessions)) # Предзагрузка связанных игровых сессий
|
||||
.filter_by(user_id=user_id)
|
||||
.first()
|
||||
)
|
||||
return user
|
||||
except SQLAlchemyError as e:
|
||||
print(f"Ошибка при получении пользователя: {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
|
||||
# Создаём новую запись в таблице Auth
|
||||
new_auth = Auth(login=login, password=password)
|
||||
session.add(new_auth)
|
||||
|
||||
try:
|
||||
session.commit() # Сохраняем изменения в таблице Auth
|
||||
|
||||
# Создаем новую запись в таблице Users, связывая с только что добавленным Auth
|
||||
# Создаём новую запись в таблице Users, связываем с только что добавленным Auth
|
||||
new_user = Users(user_id=new_auth.user_id, username=username)
|
||||
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}")
|
||||
|
|
@ -43,28 +58,18 @@ def create_user(login, password, username):
|
|||
finally:
|
||||
session.close()
|
||||
|
||||
return True, "Регистрация успешна."
|
||||
|
||||
|
||||
def check_user(login, password=None):
|
||||
"""Проверка существования пользователя по логину и паролю (если передан)."""
|
||||
session = get_session()
|
||||
try:
|
||||
print(f"Проверяем пользователя с логином: {login}")
|
||||
# Фильтрация только по логину
|
||||
query = session.query(Auth).filter_by(login=login)
|
||||
|
||||
# Если передан пароль, фильтруем и по паролю
|
||||
if password:
|
||||
query = query.filter_by(password=password)
|
||||
|
||||
user = query.first()
|
||||
|
||||
if user:
|
||||
print(f"Пользователь найден: {user.user_id}")
|
||||
return user.user_id # Возвращаем user_id пользователя
|
||||
return user.user_id
|
||||
else:
|
||||
print("Пользователь не найден.")
|
||||
return None
|
||||
except SQLAlchemyError as e:
|
||||
print(f"Ошибка при проверке пользователя: {e}")
|
||||
|
|
@ -76,6 +81,8 @@ 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,
|
||||
|
|
@ -89,8 +96,10 @@ def save_progress(user_id, level, score, duration, health, hunger, sleepiness):
|
|||
session.add(session_data)
|
||||
session.commit()
|
||||
except SQLAlchemyError as e:
|
||||
print(f"Ошибка при сохранении прогресса: {e}")
|
||||
logging.error(f"Ошибка при сохранении прогресса: {e}")
|
||||
session.rollback()
|
||||
except ValueError as e:
|
||||
logging.error(e)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
|
@ -100,7 +109,7 @@ def get_user_progress(user_id):
|
|||
try:
|
||||
return session.query(GameSession).filter_by(user_id=user_id).all()
|
||||
except Exception as e:
|
||||
print(f"Ошибка при получении прогресса пользователя: {e}")
|
||||
logging.error(f"Ошибка при получении прогресса пользователя: {e}")
|
||||
return []
|
||||
finally:
|
||||
session.close()
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
import logging
|
||||
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from database.db_session import get_session
|
||||
from database.models import Dogs
|
||||
|
||||
|
|
@ -47,21 +51,44 @@ DOG_CHARACTERS = {
|
|||
}
|
||||
|
||||
def populate_dogs():
|
||||
"""
|
||||
Заполнение таблицы Dogs предустановленными данными.
|
||||
"""
|
||||
session = get_session()
|
||||
try:
|
||||
logging.info("Начинается заполнение таблицы Dogs.")
|
||||
for breed, data in DOG_CHARACTERS.items():
|
||||
dog = Dogs(
|
||||
breed=breed,
|
||||
characteristics=data['characteristics'],
|
||||
behavior=data['behavior'],
|
||||
care_info=data['care_info'],
|
||||
admin_comments=data['admin_comments']
|
||||
)
|
||||
session.add(dog)
|
||||
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()
|
||||
print("Таблица Dogs успешно заполнена.")
|
||||
except Exception as e:
|
||||
logging.info("Таблица Dogs успешно заполнена.")
|
||||
except SQLAlchemyError as e:
|
||||
session.rollback()
|
||||
print(f"Ошибка при заполнении Dogs: {e}")
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -1,34 +1,48 @@
|
|||
import logging
|
||||
from sqlalchemy import func
|
||||
from database.db_events import get_user_progress
|
||||
from database.db_session import get_session
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from database.models import GameSession
|
||||
|
||||
|
||||
def save_game_session(user_id, level, score, duration, health, hunger, sleepiness):
|
||||
"""Сохранение игрового процесса в таблицу GameSessions."""
|
||||
def save_game_session(user_id, level, score, steps, duration=0, health=100, hunger=0, sleepiness=0):
|
||||
"""Сохранение игрового прогресса."""
|
||||
session = get_session()
|
||||
try:
|
||||
# Создаем новый объект GameSession
|
||||
game_session = GameSession(
|
||||
session.add(GameSession(
|
||||
user_id=user_id,
|
||||
level=level,
|
||||
score=score,
|
||||
steps=steps,
|
||||
duration=duration,
|
||||
health=health,
|
||||
hunger=hunger,
|
||||
sleepiness=sleepiness,
|
||||
)
|
||||
session.add(game_session)
|
||||
session.commit() # Сохраняем данные в таблице
|
||||
print(f"Игровой процесс для пользователя {user_id} на уровне {level} успешно сохранен.")
|
||||
except SQLAlchemyError as e:
|
||||
sleepiness=sleepiness
|
||||
))
|
||||
session.commit()
|
||||
logging.info(f"Сессия сохранена: user_id={user_id}, level={level}, score={score}")
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
print(f"Ошибка при сохранении игрового процесса: {e}")
|
||||
finally:
|
||||
session.close()
|
||||
logging.error(f"Ошибка при сохранении игровой сессии: {e}")
|
||||
raise
|
||||
|
||||
|
||||
def print_user_progress(user_id):
|
||||
"""Печать прогресса пользователя из таблицы GameSessions."""
|
||||
"""
|
||||
Печать прогресса пользователя из таблицы 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} секунд")
|
||||
print(f"- Уровень: {session.level}, Очки: {session.score}, Время: {session.duration} сек")
|
||||
|
|
|
|||
5116
logs/logfile.log
5116
logs/logfile.log
File diff suppressed because it is too large
Load diff
56
src/auth.py
56
src/auth.py
|
|
@ -1,3 +1,5 @@
|
|||
import logging
|
||||
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from database.db_session import get_session
|
||||
from database.models import Auth, Users, GameSession
|
||||
|
|
@ -6,50 +8,42 @@ from database.models import Auth, Users, GameSession
|
|||
def register_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
|
||||
if session.query(Auth).filter_by(login=login).first():
|
||||
return False, "Логин уже используется."
|
||||
|
||||
# Создаем новую запись в таблице Users, связывая с только что добавленным Auth
|
||||
# Используем new_auth.user_id для связи
|
||||
# Создаем новую запись в Auth
|
||||
new_auth = Auth(login=login, password=password)
|
||||
session.add(new_auth)
|
||||
session.commit()
|
||||
|
||||
# Создаем запись в Users
|
||||
new_user = Users(user_id=new_auth.user_id, username=username)
|
||||
session.add(new_user)
|
||||
session.commit() # Сохраняем изменения в таблице Users
|
||||
|
||||
# Создаем новый игровой процесс в GameSession для этого пользователя
|
||||
new_game_session = GameSession(user_id=new_user.user_id, level=1) # Устанавливаем уровень по умолчанию
|
||||
# Создаем запись в GameSession
|
||||
new_game_session = GameSession(user_id=new_user.user_id, level=1)
|
||||
session.add(new_game_session)
|
||||
session.commit() # Сохраняем данные в GameSession
|
||||
session.commit()
|
||||
|
||||
print(f"Пользователь {username} успешно добавлен!")
|
||||
return True, "Регистрация успешна."
|
||||
except SQLAlchemyError as e:
|
||||
session.rollback() # Откат изменений при ошибке
|
||||
print(f"Ошибка при создании пользователя: {e}")
|
||||
session.rollback()
|
||||
logging.error(f"Ошибка при регистрации: {e}")
|
||||
return False, "Произошла ошибка при регистрации."
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return True, "Регистрация успешна."
|
||||
|
||||
|
||||
def login_user(login, password):
|
||||
"""Авторизация пользователя."""
|
||||
session = get_session()
|
||||
|
||||
# Проверяем, существует ли пользователь с таким логином и паролем
|
||||
user_auth = session.query(Auth).filter_by(login=login, password=password).first()
|
||||
|
||||
if user_auth:
|
||||
# Возвращаем успешный вход и ID пользователя из таблицы Users
|
||||
user = session.query(Users).filter_by(user_id=user_auth.user_id).first()
|
||||
return True, user.user_id
|
||||
|
||||
return False, "Неверный логин или пароль."
|
||||
try:
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
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 database.db_events import create_user, check_user
|
||||
from src.ui.user_ui.main_menu import UserApp
|
||||
|
||||
class DogAcademyApp:
|
||||
def __init__(self, root):
|
||||
def __init__(self, root, user_id=None):
|
||||
"""Инициализация приложения."""
|
||||
self.root = root
|
||||
self.user_id = user_id
|
||||
self.root.title("Dog Academy Game")
|
||||
self.root.geometry("1920x1080")
|
||||
self.root.configure(bg=BACKGROUND_COLOR)
|
||||
|
|
@ -20,12 +24,11 @@ class DogAcademyApp:
|
|||
self.current_frame.destroy()
|
||||
|
||||
def show_main_menu(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="Dog Academy Game",
|
||||
|
|
@ -35,7 +38,6 @@ class DogAcademyApp:
|
|||
)
|
||||
title.pack(pady=50)
|
||||
|
||||
# Кнопка "Войти"
|
||||
login_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Войти",
|
||||
|
|
@ -46,7 +48,6 @@ class DogAcademyApp:
|
|||
)
|
||||
login_button.pack(pady=20)
|
||||
|
||||
# Кнопка "Зарегистрироваться"
|
||||
register_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Зарегистрироваться",
|
||||
|
|
@ -63,7 +64,6 @@ class DogAcademyApp:
|
|||
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
||||
self.current_frame.pack(expand=True)
|
||||
|
||||
# Заголовок
|
||||
title = tk.Label(
|
||||
self.current_frame,
|
||||
text="Авторизация",
|
||||
|
|
@ -73,19 +73,16 @@ class DogAcademyApp:
|
|||
)
|
||||
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.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.pack(pady=10)
|
||||
|
||||
# Кнопка "Показать пароль"
|
||||
show_password_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Показать пароль",
|
||||
|
|
@ -96,7 +93,6 @@ class DogAcademyApp:
|
|||
)
|
||||
show_password_button.pack(pady=10)
|
||||
|
||||
# Кнопка "Войти"
|
||||
login_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Войти",
|
||||
|
|
@ -107,7 +103,6 @@ class DogAcademyApp:
|
|||
)
|
||||
login_button.pack(pady=20)
|
||||
|
||||
# Кнопка "Вернуться на главную"
|
||||
back_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Вернуться на главную",
|
||||
|
|
@ -132,17 +127,21 @@ class DogAcademyApp:
|
|||
|
||||
if login == ADMIN_LOGIN and password == ADMIN_PASSWORD:
|
||||
messagebox.showinfo("Успех", "Вы успешно авторизованы как администратор!")
|
||||
self.show_admin_panel() # Переходим к админ-панели
|
||||
elif check_user(login, password):
|
||||
messagebox.showinfo("Успех", "Вы успешно авторизованы!")
|
||||
self.show_user_dashboard() # Переходим к панели пользователя
|
||||
self.user_id = None # Администратору не нужен user_id
|
||||
self.show_admin_panel()
|
||||
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):
|
||||
"""Отображение интерфейса администратора."""
|
||||
self.clear_frame()
|
||||
AdminApp(self.root) # Создаем экземпляр админ-панели
|
||||
AdminApp(self.root)
|
||||
|
||||
def show_registration_screen(self):
|
||||
"""Показать экран регистрации."""
|
||||
|
|
@ -150,7 +149,6 @@ class DogAcademyApp:
|
|||
self.current_frame = tk.Frame(self.root, bg=BACKGROUND_COLOR)
|
||||
self.current_frame.pack(expand=True)
|
||||
|
||||
# Заголовок
|
||||
title = tk.Label(
|
||||
self.current_frame,
|
||||
text="Регистрация",
|
||||
|
|
@ -160,36 +158,21 @@ class DogAcademyApp:
|
|||
)
|
||||
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.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.pack(pady=10)
|
||||
|
||||
# Кнопка "Показать пароль"
|
||||
show_password_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Показать пароль",
|
||||
bg=BUTTON_COLOR,
|
||||
fg=BUTTON_TEXT_COLOR,
|
||||
font=FONT,
|
||||
command=self.toggle_registration_password,
|
||||
)
|
||||
show_password_button.pack(pady=10)
|
||||
|
||||
# Никнейм
|
||||
username_label = tk.Label(self.current_frame, text="Никнейм:", bg=BACKGROUND_COLOR, fg=PRIMARY_COLOR, font=FONT)
|
||||
username_label.pack()
|
||||
self.username_entry = tk.Entry(self.current_frame, font=FONT)
|
||||
self.username_entry.pack(pady=10)
|
||||
|
||||
# Кнопка "Зарегистрироваться"
|
||||
register_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Зарегистрироваться",
|
||||
|
|
@ -200,7 +183,6 @@ class DogAcademyApp:
|
|||
)
|
||||
register_button.pack(pady=20)
|
||||
|
||||
# Кнопка "Вернуться на главную"
|
||||
back_button = tk.Button(
|
||||
self.current_frame,
|
||||
text="Вернуться на главную",
|
||||
|
|
@ -222,19 +204,19 @@ class DogAcademyApp:
|
|||
"""Регистрация нового пользователя."""
|
||||
login = self.reg_login_entry.get()
|
||||
password = self.reg_password_entry.get()
|
||||
username = self.username_entry.get() # Получаем имя пользователя
|
||||
username = self.username_entry.get()
|
||||
|
||||
if login and password and username:
|
||||
success, message = create_user(login, password, username) # Передаем имя пользователя
|
||||
success, message = create_user(login, password, username)
|
||||
if success:
|
||||
messagebox.showinfo("Успех", message)
|
||||
self.show_login_screen()
|
||||
else:
|
||||
messagebox.showerror("Ошибка", message)
|
||||
else:
|
||||
messagebox.showerror("Ошибка", "Пожалуйста, заполните все поля.")
|
||||
messagebox.showerror("Ошибка", "Заполните все поля.")
|
||||
|
||||
def show_user_dashboard(self):
|
||||
"""Переход к пользовательскому интерфейсу."""
|
||||
self.clear_frame()
|
||||
"""Перейти к главному меню пользователя после авторизации."""
|
||||
UserApp(self.root)
|
||||
UserApp(self.root, self.user_id)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
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
|
||||
from database.db_events import get_user_by_id, get_user_progress, save_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
|
||||
|
|
@ -12,14 +13,22 @@ 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.max_unlocked_level = 1
|
||||
self.completed_levels = set()
|
||||
|
||||
self.total_bones = 0
|
||||
|
|
@ -28,6 +37,11 @@ class GameUI:
|
|||
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
|
||||
|
||||
# Изображения
|
||||
self.done_image = ImageTk.PhotoImage(Image.open(DONE).resize((50, 50), Image.Resampling.LANCZOS))
|
||||
|
|
@ -45,7 +59,7 @@ class GameUI:
|
|||
# Флаги
|
||||
self.is_pause_menu_open = False
|
||||
self.is_victory_screen_open = False
|
||||
self.is_game_active = False # Для контроля состояния игры
|
||||
self.is_game_active = False
|
||||
|
||||
# Привязка клавиш
|
||||
self.root.bind("<KeyPress-w>", self.move_up)
|
||||
|
|
@ -57,6 +71,15 @@ class GameUI:
|
|||
# Отображение начального экрана
|
||||
self.show_dog_selection()
|
||||
|
||||
# Инициализация интерфейса
|
||||
self.create_main_menu_button()
|
||||
|
||||
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:
|
||||
|
|
@ -122,62 +145,99 @@ class GameUI:
|
|||
clear_frame(self.root)
|
||||
self.create_background()
|
||||
|
||||
tk.Label(
|
||||
self.root, text="Выберите уровень", font=("Comic Sans MS", 24), bg="#E5E5E5"
|
||||
).pack(pady=20)
|
||||
tk.Label(self.root, text="Выберите уровень", font=("Comic Sans MS", 24), bg="#E5E5E5").pack(pady=20)
|
||||
|
||||
level_frame = tk.Frame(self.root, bg="#E5E5E5")
|
||||
level_frame.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
|
||||
|
||||
for level in range(1, 6):
|
||||
progress = get_user_progress(self.user_id)
|
||||
completed_levels = {session.level for session in progress if session.score > 0}
|
||||
self.max_unlocked_level = max(completed_levels) if completed_levels else 1
|
||||
|
||||
for level in range(1, 101):
|
||||
color = (
|
||||
"#4CAF50" if level in 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(
|
||||
level_frame,
|
||||
text=f"Уровень {level}",
|
||||
state=tk.NORMAL if level <= self.max_unlocked_level else tk.DISABLED,
|
||||
font=("Comic Sans MS", 20),
|
||||
bg="#4CAF50" if level <= self.max_unlocked_level else "#A9A9A9",
|
||||
width=15,
|
||||
height=2,
|
||||
command=lambda l=level: self.start_level(l),
|
||||
bg=color,
|
||||
state=state,
|
||||
font=("Comic Sans MS", 14),
|
||||
command=lambda l=level: self.handle_level_selection(l)
|
||||
)
|
||||
button.pack(pady=10)
|
||||
button.grid(row=(level - 1) // 10, column=(level - 1) % 10, padx=5, pady=5)
|
||||
|
||||
tk.Button(
|
||||
self.root,
|
||||
text="Вернуться",
|
||||
font=("Comic Sans MS", 16),
|
||||
bg="lightgreen",
|
||||
command=self.show_dog_selection,
|
||||
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.current_level = level
|
||||
self.total_bones = 0
|
||||
self.steps_taken = 0
|
||||
self.start_game()
|
||||
elif level <= self.max_unlocked_level:
|
||||
self.current_level = level
|
||||
self.countdown()
|
||||
else:
|
||||
messagebox.showinfo("Недоступно", "Пройдите предыдущие уровни, чтобы разблокировать этот.")
|
||||
|
||||
def start_level(self, level):
|
||||
"""Начало выбранного уровня."""
|
||||
self.current_level = level
|
||||
self.countdown()
|
||||
"""Запуск уровня."""
|
||||
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)
|
||||
"""Обратный отсчёт перед началом уровня с анимацией."""
|
||||
clear_frame(self.root) # Очищаем экран
|
||||
countdown_label = tk.Label(
|
||||
self.root, text="", font=("Comic Sans MS", 30), bg="#E5E5E5"
|
||||
self.root, text="Готовьтесь!", font=("Comic Sans MS", 40), bg="#E5E5E5"
|
||||
)
|
||||
countdown_label.pack(expand=True)
|
||||
|
||||
for i in range(3, 0, -1):
|
||||
countdown_label.config(text=f"{i}...")
|
||||
self.root.update()
|
||||
self.root.after(1000)
|
||||
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, self.start_game)
|
||||
|
||||
self.start_game()
|
||||
update_countdown(3) # Старт обратного отсчёта с 3 секунд
|
||||
|
||||
def start_game(self):
|
||||
"""Запуск игрового процесса."""
|
||||
clear_frame(self.root)
|
||||
logging.info(f"Игра начата на уровне {self.current_level}")
|
||||
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.bones_positions = self.generate_bones()
|
||||
self.bones_positions = self.generate_bones() # Генерация новых косточек
|
||||
|
||||
# Прямоугольник и изображение косточек (создаются один раз)
|
||||
self.rect_x1, self.rect_y1 = 1600, 0
|
||||
|
|
@ -189,11 +249,6 @@ class GameUI:
|
|||
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)
|
||||
|
||||
# В методе update_map (не удаляем прямоугольник):
|
||||
self.map_canvas.delete("all") # Удаляем только динамичные объекты карты (косточки, собаку)
|
||||
self.draw_grid()
|
||||
self.collect_bones()
|
||||
|
||||
self.update_map() # Начальное обновление карты
|
||||
|
||||
def draw_grid(self):
|
||||
|
|
@ -204,11 +259,15 @@ class GameUI:
|
|||
self.map_canvas.create_line(0, y, 1920, y, fill="lightgray")
|
||||
|
||||
def generate_bones(self):
|
||||
"""Генерация косточек на карте."""
|
||||
return [
|
||||
"""Генерация косточек на карте с увеличением их количества по геометрической прогрессии."""
|
||||
# Количество косточек увеличивается по геометрической прогрессии
|
||||
bones_count = min(5, 10 * (2 ** (self.current_level - 1))) # Ограничение в 5 косточек на уровне
|
||||
bones = [
|
||||
(random.randint(0, self.cols - 1), random.randint(0, self.rows - 1))
|
||||
for _ in range(2)
|
||||
for _ in range(bones_count)
|
||||
]
|
||||
logging.info(f"Генерация косточек: {bones}") # Логируем координаты косточек
|
||||
return bones
|
||||
|
||||
def collect_bones(self):
|
||||
"""Проверка и сбор косточек."""
|
||||
|
|
@ -216,10 +275,19 @@ class GameUI:
|
|||
if self.dog_position == [bone[0], bone[1]]:
|
||||
self.bones_positions.remove(bone)
|
||||
self.total_bones += 1
|
||||
|
||||
# Сохранение прогресса
|
||||
save_progress(self.user_id, self.current_level, self.total_bones, self.steps_taken, 100, 0, 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:
|
||||
self.show_victory_screen() # Показываем экран победы
|
||||
|
||||
if self.steps_taken % 10 == 0 and len(self.bones_positions) < self.max_bones_per_level:
|
||||
self.bones_positions.extend(self.generate_bones())
|
||||
self.bones_positions.extend(self.generate_bones()) # Генерация новых косточек, если нужно
|
||||
|
||||
def move_up(self, event):
|
||||
"""Движение вверх."""
|
||||
|
|
@ -299,6 +367,7 @@ class GameUI:
|
|||
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):
|
||||
"""Сохранение данных и выход в главное меню."""
|
||||
|
|
@ -313,8 +382,8 @@ class GameUI:
|
|||
if self.is_victory_screen_open: # Отключаем обновления, если окно победы открыто
|
||||
return
|
||||
|
||||
self.map_canvas.delete("all")
|
||||
self.draw_grid()
|
||||
self.map_canvas.delete("all") # Удаляем старые объекты карты
|
||||
self.draw_grid() # Перерисовываем сетку
|
||||
|
||||
# Отображение косточек
|
||||
for x, y in self.bones_positions:
|
||||
|
|
@ -325,14 +394,17 @@ class GameUI:
|
|||
)
|
||||
|
||||
# Отображение собаки
|
||||
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
|
||||
)
|
||||
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()
|
||||
|
|
@ -344,17 +416,17 @@ class GameUI:
|
|||
|
||||
def show_victory_screen(self):
|
||||
"""Экран победы."""
|
||||
if self.is_victory_screen_open: # Проверяем, чтобы не было второго окна
|
||||
if self.is_victory_screen_open:
|
||||
return
|
||||
|
||||
self.is_victory_screen_open = True # Устанавливаем флаг
|
||||
self.is_game_active = False # Останавливаем движение
|
||||
self.is_victory_screen_open = True
|
||||
self.is_game_active = False
|
||||
|
||||
victory_window = tk.Toplevel(self.root)
|
||||
victory_window.title("Ура, победа!")
|
||||
victory_window.geometry("800x600")
|
||||
victory_window.configure(bg="#E5E5E5")
|
||||
victory_window.grab_set() # Блокируем взаимодействие с основным окном
|
||||
victory_window.grab_set()
|
||||
|
||||
# Изображение собаки
|
||||
dog_image = Image.open(DOG_CHARACTERS[self.selected_dog]["image"]).resize((200, 200), Image.Resampling.LANCZOS)
|
||||
|
|
@ -364,26 +436,26 @@ class GameUI:
|
|||
dog_label.place(x=50, y=50)
|
||||
|
||||
# Текст победы
|
||||
victory_label = tk.Label(
|
||||
victory_window, text="Ура, победа!", font=("Comic Sans MS", 24), bg="#E5E5E5"
|
||||
)
|
||||
victory_label = tk.Label(victory_window, text="Ура, победа!", font=("Comic Sans MS", 24), bg="#E5E5E5")
|
||||
victory_label.pack(pady=20)
|
||||
|
||||
# Характеристики собаки
|
||||
dog_info = f"Порода: {self.selected_dog}"
|
||||
info_label = tk.Label(
|
||||
victory_window, text=dog_info, font=("Comic Sans MS", 16), bg="#E5E5E5"
|
||||
)
|
||||
info_label = tk.Label(victory_window, text=dog_info, font=("Comic Sans MS", 16), bg="#E5E5E5")
|
||||
info_label.place(x=300, y=100)
|
||||
|
||||
# Собрано косточек
|
||||
target_bones = 10 * (2 ** (self.current_level - 1)) # Геометрическая прогрессия для косточек
|
||||
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 = tk.Label(victory_window, text=collected_info, font=("Comic Sans MS", 16), bg="#E5E5E5")
|
||||
score_label.place(x=300, y=150)
|
||||
|
||||
# Никнейм игрока
|
||||
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=200)
|
||||
|
||||
# Кнопка перехода на следующий уровень
|
||||
next_level_button = tk.Button(
|
||||
victory_window,
|
||||
|
|
@ -404,29 +476,91 @@ class GameUI:
|
|||
)
|
||||
exit_button.place(relx=0.5, rely=0.8, anchor=tk.CENTER)
|
||||
|
||||
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):
|
||||
"""Возврат в главное меню."""
|
||||
self.is_victory_screen_open = False # Сбрасываем флаг окна победы
|
||||
self.return_to_main_menu_callback() # Вызываем колбэк для возврата
|
||||
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.save_progress() # Сохраняем прогресс перед переходом на следующий уровень
|
||||
try:
|
||||
# Сохранение текущего прогресса
|
||||
self.save_progress()
|
||||
|
||||
# Переход на следующий уровень
|
||||
self.current_level += 1
|
||||
self.total_bones = 0 # Сбрасываем счётчик косточек
|
||||
self.start_level(self.current_level)
|
||||
# Переход на следующий уровень
|
||||
self.current_level += 1
|
||||
self.max_unlocked_level = max(self.max_unlocked_level, self.current_level)
|
||||
|
||||
# Сброс состояния игры: собака возвращается в начальную позицию
|
||||
self.total_bones = 0
|
||||
self.steps_taken = 0
|
||||
self.dog_position = [1, 1] # Начальная позиция собаки
|
||||
self.bones_positions = [] # Очищаем текущие косточки
|
||||
|
||||
# Генерация новых косточек с увеличением их количества по геометрической прогрессии
|
||||
self.bones_positions = self.generate_bones()
|
||||
|
||||
# Начинаем новый уровень с обратным отсчётом
|
||||
self.countdown() # Запуск обратного отсчёта
|
||||
except Exception as e:
|
||||
logging.error(f"Ошибка при переходе на следующий уровень: {e}")
|
||||
|
||||
def save_progress(self):
|
||||
"""Сохранение игрового процесса в таблицу GameSessions."""
|
||||
from datetime import datetime
|
||||
if not self.user_id:
|
||||
logging.error("Ошибка: user_id равен None. Запись невозможна.")
|
||||
return
|
||||
|
||||
# Получаем время начала и окончания уровня
|
||||
duration = self.steps_taken # Время можно рассчитать по шагам или в реальном времени
|
||||
score = self.total_bones # Количество собранных косточек
|
||||
try:
|
||||
# Рассчитываем длительность уровня и текущий счет
|
||||
duration = self.steps_taken
|
||||
score = self.total_bones
|
||||
|
||||
# Сохранение прогресса в базу данных
|
||||
save_game_session(self.user_id, self.current_level, score, duration, 100, 0, 0)
|
||||
# Логирование
|
||||
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() # Вызов колбэка для возврата в главное меню
|
||||
|
||||
# Также можно сохранять дополнительные параметры, если необходимо (например, здоровье, голод, усталость)
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import logging
|
||||
import tkinter as tk
|
||||
from functools import partial
|
||||
from tkinter import messagebox, Canvas
|
||||
from PIL import Image, ImageTk
|
||||
import math
|
||||
|
|
@ -31,10 +32,11 @@ PLAY_BUTTON_RADIUS = 100 # Радиус кнопки "Играть"
|
|||
|
||||
|
||||
class UserApp:
|
||||
def __init__(self, root, user_id=None):
|
||||
def __init__(self, root, user_id):
|
||||
"""Инициализация пользовательского интерфейса."""
|
||||
self.root = root
|
||||
self.user_id = user_id
|
||||
self.root.configure(bg=BACKGROUND_COLOR)
|
||||
self.root.configure(bg="#E5E5E5")
|
||||
self.root.geometry("1920x1080")
|
||||
self.root.title("Собачья академия")
|
||||
self.show_user_dashboard()
|
||||
|
|
@ -151,8 +153,12 @@ class UserApp:
|
|||
|
||||
def show_profile(self):
|
||||
"""Показать экран профиля пользователя."""
|
||||
self.clear_frame()
|
||||
profile_ui(self.root, self.user_id, self) # Передаем сам объект self для доступа к show_user_dashboard
|
||||
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):
|
||||
"""Очистить текущий экран."""
|
||||
|
|
@ -160,14 +166,15 @@ class UserApp:
|
|||
widget.destroy()
|
||||
|
||||
def play_game(self):
|
||||
"""Переход к игровому интерфейсу."""
|
||||
print("Запуск игры...")
|
||||
"""Запуск игры и передача колбэка для возврата в меню."""
|
||||
# Передаем метод через 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():
|
||||
clear_frame(self.root)
|
||||
self.show_user_dashboard() # Возврат в главное меню
|
||||
|
||||
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):
|
||||
"""Подтверждение выхода из приложения."""
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import tkinter as tk
|
||||
from src.utils import clear_frame
|
||||
from database.db_events import get_user_progress
|
||||
from database.db_events import get_user_progress, get_user_by_id
|
||||
|
||||
|
||||
def profile_ui(root, user_id, user_app):
|
||||
|
|
@ -10,12 +10,24 @@ def profile_ui(root, user_id, user_app):
|
|||
frame = tk.Frame(root, bg="#f8e1e1")
|
||||
frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
tk.Label(frame, text="Профиль", font=("Comic Sans MS", 30), bg="#f8e1e1").pack(pady=20)
|
||||
# Обновляем данные пользователя из базы
|
||||
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)
|
||||
|
||||
# Получение прогресса пользователя из базы данных
|
||||
progress = get_user_progress(user_id)
|
||||
levels_completed = len(progress) # Считаем количество уровней
|
||||
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)
|
||||
|
|
@ -24,7 +36,7 @@ def profile_ui(root, user_id, user_app):
|
|||
back_button = tk.Button(
|
||||
frame,
|
||||
text="Назад",
|
||||
command=lambda: [clear_frame(root), user_app.show_user_dashboard()], # Очистить экран и вернуться на главное меню
|
||||
command=lambda: [clear_frame(root), user_app.show_user_dashboard()],
|
||||
font=("Comic Sans MS", 20)
|
||||
)
|
||||
back_button.pack(pady=20)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,9 @@
|
|||
import logging
|
||||
import time
|
||||
import tkinter as tk
|
||||
from src.utils import clear_frame
|
||||
from database.db_events import save_progress
|
||||
|
||||
|
||||
def start_game(root, user_id, dog_id):
|
||||
"""Игровой процесс."""
|
||||
clear_frame(root)
|
||||
|
||||
# Обратный отсчет
|
||||
for i in range(3, 0, -1):
|
||||
clear_frame(root)
|
||||
tk.Label(root, text=f"{i}...", font=("Comic Sans MS", 30)).pack(expand=True)
|
||||
root.update()
|
||||
time.sleep(1) # Пауза между отсчетами
|
||||
|
||||
# Начало уровня
|
||||
print("Начало уровня") # Для отладки
|
||||
|
||||
# Здесь подключается логика работы с картой и вопросами
|
||||
pass
|
||||
|
||||
|
||||
def handle_checkpoint(obstacle, current_score, root):
|
||||
"""
|
||||
Обрабатывает чек-поинт (косточку).
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
|
||||
def setup_logging():
|
||||
"""Настройка логирования в файл."""
|
||||
log_file = "logs/game.log"
|
||||
if not os.path.exists(log_file):
|
||||
os.makedirs(log_file)
|
||||
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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue