Изменён пользовательский интерфейс main_menu.py, game_ui.py. Настроен вызов функций для запуска игрового процесса: после нажатия кнопки 'играть' открывается выбор собаки, а затем выбор уровня. Обновлена структура базы данных. Удалены не нужные файлы для проекта.
BIN
assets/background.png
Normal file
|
After Width: | Height: | Size: 821 KiB |
BIN
assets/bone.png
Normal file
|
After Width: | Height: | Size: 142 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/logo.png
Normal file
|
After Width: | Height: | Size: 87 KiB |
103
config.py
|
|
@ -6,7 +6,7 @@ ADMIN_BUTTON_TEXT_COLOR = "#ffffff"
|
|||
ADMIN_FONT = ("Comic Sans MS", 25)
|
||||
ADMIN_BIG_FONT = ("Comic Sans MS", 40)
|
||||
|
||||
# Интерфейс пользователя
|
||||
# Интерфейс пользователя (АВТОРИЗАЦИЯ)
|
||||
BACKGROUND_COLOR = "#f8e1e1"
|
||||
PRIMARY_COLOR = "#ff6347"
|
||||
BUTTON_COLOR = "#87ceeb"
|
||||
|
|
@ -14,6 +14,26 @@ BUTTON_TEXT_COLOR = "white"
|
|||
FONT = ("Comic Sans MS", 25)
|
||||
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_PASSWORD = "admin123"
|
||||
|
|
@ -23,23 +43,78 @@ DATABASE_URL = "sqlite:///database/DogAcademy.db" # Обновлено на п
|
|||
|
||||
# Иконки
|
||||
SETTINGS_IMG = "assets/settings.png"
|
||||
LOGO = "F:/Projects/Dog_Academy/assets/logo.png"
|
||||
BACKGROUND_GAME = "F:/Projects/Dog_Academy/assets/background.png"
|
||||
BONE = "F:/Projects/Dog_Academy/assets/bone.png"
|
||||
|
||||
# Собаки
|
||||
CHIHUAHUA = "F:/Projects/Dog_Academy/assets/dogs/Chihuahua.png"
|
||||
CORGI = "F:/Projects/Dog_Academy/assets/dogs/Corgi.png"
|
||||
RETRIEVER = "F:/Projects/Dog_Academy/assets/dogs/Golden_Retriever.png"
|
||||
HUSKY = "F:/Projects/Dog_Academy/assets/dogs/Husky.png"
|
||||
POMERANIAN = "F:/Projects/Dog_Academy/assets/dogs/Pomeranian.png"
|
||||
PUG = "F:/Projects/Dog_Academy/assets/dogs/Pug.png"
|
||||
YORKSHIRE = "F:/Projects/Dog_Academy/assets/dogs/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
|
||||
|
||||
# ГЛАВНОЕ МЕНЮ
|
||||
BACKGROUND_COLOR_USER = "#bcabe5" # Основной фон
|
||||
TOP_PANEL_COLOR_USER = "#aa9bcd" # Цвет верхней панели
|
||||
BUTTON_COLOR_PROFILE_USER = "#a2c792" # Цвет кнопок "Профиль", "Магазин", "База знаний"
|
||||
BUTTON_COLOR_PLAY_USER = "#b4e1a1" # Цвет кнопки "Играть"
|
||||
BUTTON_COLOR_EXIT_USER = "#a2c792" # Цвет кнопки "Выход"
|
||||
# Игровые параметры
|
||||
INITIAL_SCORE = 5 # Начальные очки игрока
|
||||
POINTS_CORRECT_ANSWER = 2 # Очки за правильный ответ
|
||||
POINTS_WRONG_ANSWER = -1 # Штраф за неправильный ответ
|
||||
MAX_LEVELS = 100 # Максимальное количество уровней
|
||||
INITIAL_DOG_STATUS = {"health": 100, "hunger": 0, "sleepiness": 0} # Стартовые характеристики собаки
|
||||
|
||||
# Текст и шрифты
|
||||
BUTTON_TEXT_COLOR_USER = "white" # Цвет текста на кнопках
|
||||
FONT_USER = ("Comic Sans MS", 20) # Шрифт для текста кнопок
|
||||
BIG_FONT_USER = ("Comic Sans MS", 30) # Большой шрифт (например, для заголовков)
|
||||
# Параметры карты
|
||||
MIN_OBSTACLES = 3 # Минимум препятствий на уровне
|
||||
MAX_OBSTACLES = 6 # Максимум препятствий на уровне
|
||||
|
||||
# Размеры кнопок
|
||||
BUTTON_RADIUS_USER = 50 # Радиус круглой кнопки
|
||||
EXIT_BUTTON_SIZE_USER = (80, 40) # Размер кнопки "Выход"
|
||||
# Графика и анимация
|
||||
COUNTDOWN_DURATION = 3 # Продолжительность обратного отсчёта в секундах
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
from sqlalchemy import func
|
||||
from sqlalchemy.orm import joinedload
|
||||
from database.db_session import get_session
|
||||
from database.models import Auth, Notifications, Users
|
||||
from database.models import Auth, Notifications, Users, GameSession, Dogs, Questions
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
def create_user(login, password):
|
||||
def create_user(login, password, username):
|
||||
"""Создание нового пользователя в базе данных."""
|
||||
session = get_session()
|
||||
try:
|
||||
new_user = Auth(login=login, password=password)
|
||||
new_user_auth = Auth(login=login, password=password)
|
||||
session.add(new_user_auth)
|
||||
session.commit()
|
||||
|
||||
new_user = Users(username=username, auth=new_user_auth)
|
||||
session.add(new_user)
|
||||
session.commit()
|
||||
except SQLAlchemyError as e:
|
||||
|
|
@ -20,9 +26,111 @@ def check_user(login, password):
|
|||
session = get_session()
|
||||
try:
|
||||
user = session.query(Auth).filter_by(login=login, password=password).first()
|
||||
return user is not None
|
||||
if user:
|
||||
return user.user_id
|
||||
return None
|
||||
except SQLAlchemyError as e:
|
||||
print(f"Ошибка при проверке пользователя: {e}")
|
||||
return False
|
||||
return None
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def save_progress(user_id, level, score, duration, health, hunger, sleepiness):
|
||||
"""Сохраняет прогресс пользователя в базу данных."""
|
||||
session = get_session()
|
||||
try:
|
||||
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()
|
||||
except SQLAlchemyError as e:
|
||||
print(f"Ошибка при сохранении прогресса: {e}")
|
||||
session.rollback()
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def get_user_progress(user_id):
|
||||
"""Получение прогресса пользователя по его ID."""
|
||||
session = get_session()
|
||||
try:
|
||||
progress = session.query(GameSession).filter_by(user_id=user_id).all()
|
||||
return progress
|
||||
except SQLAlchemyError as e:
|
||||
print(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()
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def get_notifications(user_id):
|
||||
"""Получение уведомлений для пользователя."""
|
||||
session = get_session()
|
||||
try:
|
||||
notifications = session.query(Notifications).filter_by(user_id=user_id).all()
|
||||
return notifications
|
||||
except SQLAlchemyError as e:
|
||||
print(f"Ошибка при получении уведомлений: {e}")
|
||||
return []
|
||||
finally:
|
||||
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()
|
||||
|
|
@ -13,7 +13,6 @@ Session = sessionmaker(bind=engine)
|
|||
# Переменная для хранения текущей сессии
|
||||
current_session = None
|
||||
|
||||
|
||||
def init_db(refresh=False):
|
||||
"""
|
||||
Инициализация базы данных: создание файла и таблиц.
|
||||
|
|
@ -33,18 +32,14 @@ def init_db(refresh=False):
|
|||
# Инициализация сессии при запуске
|
||||
current_session = get_session()
|
||||
|
||||
|
||||
def get_session():
|
||||
"""Возвращает сессию для работы с базой данных."""
|
||||
return Session()
|
||||
|
||||
|
||||
def close_sessions():
|
||||
"""Закрытие всех сессий перед выходом из программы."""
|
||||
global current_session
|
||||
if current_session is not None:
|
||||
if current_session:
|
||||
print("Закрытие сессии...")
|
||||
current_session.close() # Закрываем текущую сессию базы данных
|
||||
current_session = None
|
||||
current_session.close()
|
||||
else:
|
||||
print("Нет активной сессии для закрытия.")
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, UniqueConstraint, Boolean
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class Auth(Base):
|
||||
__tablename__ = 'auth'
|
||||
user_id = Column(Integer, primary_key=True)
|
||||
|
|
@ -50,7 +49,7 @@ class Questions(Base):
|
|||
__tablename__ = 'questions'
|
||||
question_id = Column(Integer, primary_key=True)
|
||||
dog_id = Column(Integer, ForeignKey('dogs.dog_id'))
|
||||
question_text = Column(Text, nullable=False) # Исправлено поле
|
||||
question_text = Column(Text, nullable=False)
|
||||
image_url = Column(String)
|
||||
helpful_info = Column(Text)
|
||||
incorrect_attempts = Column(Integer, default=0)
|
||||
|
|
@ -61,24 +60,31 @@ class Questions(Base):
|
|||
|
||||
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) # Время игры в секундах
|
||||
start_time = Column(DateTime, default=func.now()) # Исправлено
|
||||
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(Integer, default=0) # 0 - не прочитано, 1 - прочитано
|
||||
is_read = Column(Boolean, default=False) # Булевый тип для read
|
||||
|
||||
# Связь с таблицей Users
|
||||
user = relationship("Users", back_populates="notifications")
|
||||
|
|
|
|||
BIN
ishodniki/background_game.psd
Normal file
BIN
ishodniki/dogs.psd
Normal file
BIN
ishodniki/user_ui.psd
Normal file
125
logs/logfile.log
|
|
@ -1343,3 +1343,128 @@ WHERE auth.login = ? AND auth.password = ?
|
|||
LIMIT ? OFFSET ?
|
||||
2024-11-25 22:36:09 - [generated in 0.00045s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-25 22:36:09 - ROLLBACK
|
||||
2024-11-26 12:26:39 - BEGIN (implicit)
|
||||
2024-11-26 12:26:39 - 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-26 12:26:39 - [generated in 0.00021s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 12:26:39 - ROLLBACK
|
||||
2024-11-26 12:33:48 - BEGIN (implicit)
|
||||
2024-11-26 12:33:48 - 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-26 12:33:48 - [generated in 0.00022s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 12:33:48 - ROLLBACK
|
||||
2024-11-26 12:38:38 - BEGIN (implicit)
|
||||
2024-11-26 12:38:38 - 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-26 12:38:38 - [generated in 0.00029s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 12:38:38 - ROLLBACK
|
||||
2024-11-26 17:00:02 - BEGIN (implicit)
|
||||
2024-11-26 17:00:02 - 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-26 17:00:02 - [generated in 0.00024s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 17:00:02 - ROLLBACK
|
||||
2024-11-26 17:01:01 - BEGIN (implicit)
|
||||
2024-11-26 17:01:01 - 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-26 17:01:01 - [generated in 0.00021s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 17:01:01 - ROLLBACK
|
||||
2024-11-26 17:07:02 - BEGIN (implicit)
|
||||
2024-11-26 17:07:02 - 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-26 17:07:02 - [generated in 0.00023s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 17:07:02 - ROLLBACK
|
||||
2024-11-26 17:08:03 - BEGIN (implicit)
|
||||
2024-11-26 17:08:03 - 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-26 17:08:03 - [generated in 0.00025s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 17:08:03 - ROLLBACK
|
||||
2024-11-26 17:27:44 - BEGIN (implicit)
|
||||
2024-11-26 17:27:44 - 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-26 17:27:44 - [generated in 0.00021s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 17:27:44 - ROLLBACK
|
||||
2024-11-26 19:46:13 - BEGIN (implicit)
|
||||
2024-11-26 19:46:13 - 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-26 19:46:13 - [generated in 0.00029s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 19:46:13 - ROLLBACK
|
||||
2024-11-26 21:23:20 - BEGIN (implicit)
|
||||
2024-11-26 21:23:20 - 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-26 21:23:20 - [generated in 0.00025s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 21:23:20 - ROLLBACK
|
||||
2024-11-26 21:31:58 - BEGIN (implicit)
|
||||
2024-11-26 21:31:58 - SELECT count(*) AS count_1
|
||||
FROM (SELECT users.user_id AS users_user_id, users.dog_id AS users_dog_id, users.username AS users_username, users.level AS users_level, users.achievement AS users_achievement
|
||||
FROM users) AS anon_1
|
||||
2024-11-26 21:31:58 - [generated in 0.00026s] ()
|
||||
2024-11-26 21:31:58 - SELECT game_sessions.level AS game_sessions_level, count(game_sessions.session_id) AS count_1
|
||||
FROM game_sessions GROUP BY game_sessions.level
|
||||
2024-11-26 21:31:58 - [generated in 0.00022s] ()
|
||||
2024-11-26 21:31:58 - SELECT questions.question_text AS questions_question_text, questions.incorrect_attempts AS questions_incorrect_attempts
|
||||
FROM questions ORDER BY questions.incorrect_attempts DESC
|
||||
2024-11-26 21:31:58 - [generated in 0.00019s] ()
|
||||
2024-11-26 21:31:58 - SELECT avg(game_sessions.duration) AS avg_1
|
||||
FROM game_sessions
|
||||
2024-11-26 21:31:58 - [generated in 0.00014s] ()
|
||||
2024-11-26 21:31:58 - ROLLBACK
|
||||
2024-11-26 21:31:58 - BEGIN (implicit)
|
||||
2024-11-26 21:31:58 - SELECT game_sessions.start_time AS game_sessions_start_time
|
||||
FROM game_sessions
|
||||
2024-11-26 21:31:58 - [generated in 0.00017s] ()
|
||||
2024-11-26 21:31:58 - ROLLBACK
|
||||
2024-11-26 21:34:57 - BEGIN (implicit)
|
||||
2024-11-26 21:34:57 - 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-26 21:34:57 - [generated in 0.00025s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 21:34:57 - ROLLBACK
|
||||
2024-11-26 21:47:02 - BEGIN (implicit)
|
||||
2024-11-26 21:47:02 - 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-26 21:47:02 - [generated in 0.00021s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 21:47:02 - ROLLBACK
|
||||
2024-11-26 21:49:25 - BEGIN (implicit)
|
||||
2024-11-26 21:49:25 - 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-26 21:49:25 - [generated in 0.00023s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 21:49:25 - ROLLBACK
|
||||
2024-11-26 21:54:33 - BEGIN (implicit)
|
||||
2024-11-26 21:54:33 - 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-26 21:54:33 - [generated in 0.00025s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 21:54:33 - ROLLBACK
|
||||
2024-11-26 22:41:31 - BEGIN (implicit)
|
||||
2024-11-26 22:41:31 - 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-26 22:41:31 - [generated in 0.00027s] ('lubluNikitu', 'meow123', 1, 0)
|
||||
2024-11-26 22:41:31 - ROLLBACK
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
import sys
|
||||
import os
|
||||
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 # Функция для закрытия сессий
|
||||
|
|
|
|||
|
|
@ -219,4 +219,4 @@ class DogAcademyApp:
|
|||
def show_user_dashboard(self):
|
||||
self.clear_frame()
|
||||
"""Перейти к главному меню пользователя после авторизации."""
|
||||
UserApp(self.root, self)
|
||||
UserApp(self.root)
|
||||
|
|
|
|||
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__/profile_ui.cpython-313.pyc
Normal file
BIN
src/ui/user_ui/__pycache__/shop_ui.cpython-313.pyc
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import tkinter as tk
|
||||
from PIL import Image, ImageTk
|
||||
from src.utils import clear_frame
|
||||
from config import DOG_CHARACTERS, BACKGROUND_GAME, LOGO, COUNTDOWN_DURATION
|
||||
from src.user_functions.map_generator import generate_map
|
||||
from src.user_functions.game_functions import handle_obstacle
|
||||
|
||||
|
||||
class GameUI:
|
||||
def __init__(self, root, user_id):
|
||||
self.root = root
|
||||
self.user_id = user_id
|
||||
self.selected_dog = None
|
||||
self.current_level = 1
|
||||
self.score = 0
|
||||
|
||||
self.root.configure(bg="lightblue")
|
||||
self.create_logo()
|
||||
self.show_dog_selection()
|
||||
|
||||
def create_logo(self):
|
||||
"""Создание логотипа."""
|
||||
logo_image = Image.open(LOGO)
|
||||
logo_photo = ImageTk.PhotoImage(logo_image.resize((200, 100), Image.Resampling.LANCZOS))
|
||||
logo_label = tk.Label(self.root, image=logo_photo, bg="lightblue")
|
||||
logo_label.image = logo_photo
|
||||
logo_label.pack(pady=10)
|
||||
|
||||
def show_dog_selection(self):
|
||||
"""Выбор собаки пользователем."""
|
||||
clear_frame(self.root)
|
||||
tk.Label(
|
||||
self.root, text="Выберите собаку", font=("Comic Sans MS", 24), bg="lightblue"
|
||||
).pack(pady=20)
|
||||
|
||||
dog_frame = tk.Frame(self.root, bg="lightblue")
|
||||
dog_frame.place(relx=0.5, rely=0.5, anchor=tk.CENTER) # Центрируем фрейм
|
||||
|
||||
for breed, details in DOG_CHARACTERS.items():
|
||||
dog_image = Image.open(details["image"])
|
||||
dog_photo = ImageTk.PhotoImage(dog_image.resize((150, 150), Image.Resampling.LANCZOS))
|
||||
|
||||
# Фрейм для кнопки и подписи
|
||||
dog_item = tk.Frame(dog_frame, bg="lightblue")
|
||||
dog_item.pack(side=tk.LEFT, padx=15, pady=15)
|
||||
|
||||
# Кнопка с изображением
|
||||
button = tk.Button(
|
||||
dog_item,
|
||||
image=dog_photo,
|
||||
command=lambda b=breed: self.confirm_dog_selection(b),
|
||||
bg="lightblue",
|
||||
borderwidth=0,
|
||||
)
|
||||
button.image = dog_photo # Сохраняем ссылку на изображение
|
||||
button.pack()
|
||||
|
||||
# Подпись с породой собаки
|
||||
tk.Label(
|
||||
dog_item,
|
||||
text=breed,
|
||||
font=("Comic Sans MS", 16),
|
||||
bg="lightblue"
|
||||
).pack(pady=5)
|
||||
|
||||
def confirm_dog_selection(self, breed):
|
||||
"""Подтверждение выбора собаки."""
|
||||
self.selected_dog = breed
|
||||
self.show_level_selection()
|
||||
|
||||
def show_level_selection(self):
|
||||
"""Отображение выбора уровня."""
|
||||
clear_frame(self.root)
|
||||
tk.Label(
|
||||
self.root, text="Выберите уровень", font=("Comic Sans MS", 20), bg="lightblue"
|
||||
).pack(pady=10)
|
||||
|
||||
level_frame = tk.Frame(self.root, bg="lightblue")
|
||||
level_frame.place(relx=0.5, rely=0.5, anchor=tk.CENTER) # Центрируем фрейм
|
||||
|
||||
for level in range(1, 6): # Доступно 5 уровней
|
||||
tk.Button(
|
||||
level_frame,
|
||||
text=f"Уровень {level}",
|
||||
command=lambda l=level: self.start_level(l),
|
||||
font=("Comic Sans MS", 16),
|
||||
bg="lightgreen",
|
||||
width=12,
|
||||
).pack(pady=10)
|
||||
|
||||
def start_level(self, level):
|
||||
"""Начало выбранного уровня."""
|
||||
self.current_level = level
|
||||
self.countdown()
|
||||
|
||||
def countdown(self):
|
||||
"""Обратный отсчёт перед началом уровня."""
|
||||
clear_frame(self.root)
|
||||
countdown_label = tk.Label(
|
||||
self.root, text="", font=("Comic Sans MS", 30), bg="lightblue"
|
||||
)
|
||||
countdown_label.pack(expand=True)
|
||||
|
||||
for i in range(COUNTDOWN_DURATION, 0, -1):
|
||||
countdown_label.config(text=f"{i}...")
|
||||
self.root.update()
|
||||
self.root.after(1000)
|
||||
|
||||
self.start_game()
|
||||
|
||||
def start_game(self):
|
||||
"""Запуск игрового процесса."""
|
||||
clear_frame(self.root)
|
||||
|
||||
# Генерация карты
|
||||
map_data = generate_map(self.current_level)
|
||||
|
||||
for obstacle in map_data:
|
||||
result = handle_obstacle(obstacle, self.score, self.root)
|
||||
self.score = result["new_score"]
|
||||
|
||||
if self.score >= 10: # Условие победы
|
||||
self.show_victory_screen()
|
||||
|
||||
def show_victory_screen(self):
|
||||
"""Экран победы."""
|
||||
clear_frame(self.root)
|
||||
|
||||
tk.Label(
|
||||
self.root, text="Ура, победа!", font=("Comic Sans MS", 30), bg="lightblue"
|
||||
).pack(pady=10)
|
||||
|
||||
dog_image = Image.open(DOG_CHARACTERS[self.selected_dog]["image"])
|
||||
dog_photo = ImageTk.PhotoImage(dog_image.resize((150, 150), Image.Resampling.LANCZOS))
|
||||
tk.Label(self.root, image=dog_photo, bg="lightblue").pack(pady=10)
|
||||
tk.Label(
|
||||
self.root,
|
||||
text=f"Порода: {self.selected_dog}\nСобрано косточек: {self.score}",
|
||||
font=("Comic Sans MS", 20),
|
||||
bg="lightblue",
|
||||
).pack(pady=10)
|
||||
|
||||
tk.Button(
|
||||
self.root,
|
||||
text="Вернуться в главное меню",
|
||||
command=lambda: self.__init__(self.root, self.user_id),
|
||||
font=("Comic Sans MS", 16),
|
||||
bg="lightgreen",
|
||||
).pack(pady=10)
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import tkinter as tk
|
||||
from src.utils import clear_frame
|
||||
from database.db_events import get_knowledge_base
|
||||
|
||||
|
||||
def knowledge_ui(root):
|
||||
"""Интерфейс базы знаний."""
|
||||
clear_frame(root)
|
||||
|
||||
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)
|
||||
|
||||
articles = get_knowledge_base()
|
||||
for article in articles:
|
||||
article_frame = tk.Frame(frame, bg="#f8f8f8", bd=2, relief=tk.RIDGE)
|
||||
article_frame.pack(pady=5, padx=10, fill=tk.X)
|
||||
|
||||
tk.Label(article_frame, text=article.breed, font=("Comic Sans MS", 20), bg="#f8f8f8").pack(side=tk.LEFT,
|
||||
padx=10)
|
||||
tk.Button(article_frame, text="Читать", command=lambda a=article: show_article(a)).pack(side=tk.RIGHT, padx=10)
|
||||
|
||||
tk.Button(frame, text="Назад", command=lambda: clear_frame(root), font=("Comic Sans MS", 20)).pack(pady=20)
|
||||
|
||||
|
||||
def show_article(article):
|
||||
"""Показать содержимое статьи."""
|
||||
top = tk.Toplevel()
|
||||
top.title(article.breed)
|
||||
text = tk.Text(top, wrap=tk.WORD)
|
||||
text.pack(fill=tk.BOTH, expand=True)
|
||||
text.insert(tk.END, article.content)
|
||||
text.config(state=tk.DISABLED)
|
||||
|
|
@ -1,78 +1,167 @@
|
|||
import tkinter as tk
|
||||
from config import (
|
||||
BACKGROUND_COLOR_USER,
|
||||
TOP_PANEL_COLOR_USER,
|
||||
BUTTON_COLOR_PROFILE_USER,
|
||||
BUTTON_COLOR_PLAY_USER,
|
||||
BUTTON_COLOR_EXIT_USER,
|
||||
BUTTON_TEXT_COLOR_USER,
|
||||
FONT_USER,
|
||||
BIG_FONT_USER,
|
||||
BUTTON_RADIUS_USER,
|
||||
EXIT_BUTTON_SIZE_USER,
|
||||
)
|
||||
from tkinter import Canvas
|
||||
from PIL import Image, ImageTk
|
||||
import math
|
||||
|
||||
from config import EXIT_BUTTON_WIDTH, EXIT_BUTTON_HEIGHT, BUTTON_COLOR_EXIT
|
||||
from src.ui.user_ui.game_ui import GameUI
|
||||
from src.ui.user_ui.profile_ui import profile_ui
|
||||
from src.ui.user_ui.shop_ui import shop_ui
|
||||
from src.ui.user_ui.knowledge_ui import knowledge_ui
|
||||
from src.utils import clear_frame
|
||||
|
||||
# Пути к изображениям собак
|
||||
DOG_IMAGES = [
|
||||
"F:/Projects/Dog_Academy/assets/dogs/Chihuahua.png",
|
||||
"F:/Projects/Dog_Academy/assets/dogs/Corgi.png",
|
||||
"F:/Projects/Dog_Academy/assets/dogs/Golden_Retriever.png",
|
||||
"F:/Projects/Dog_Academy/assets/dogs/Husky.png",
|
||||
"F:/Projects/Dog_Academy/assets/dogs/Pomeranian.png",
|
||||
"F:/Projects/Dog_Academy/assets/dogs/Pug.png",
|
||||
"F:/Projects/Dog_Academy/assets/dogs/Yorkshire_Terrier.png"
|
||||
]
|
||||
|
||||
# Настройки
|
||||
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, auth_ui):
|
||||
def __init__(self, root, user_id=None):
|
||||
self.root = root
|
||||
self.auth_ui = auth_ui
|
||||
self.root.configure(bg=BACKGROUND_COLOR_USER)
|
||||
self.root.geometry("1920x1080") # Разрешение окна
|
||||
self.user_id = user_id
|
||||
self.root.configure(bg=BACKGROUND_COLOR)
|
||||
self.root.geometry("1920x1080")
|
||||
self.root.title("Собачья академия")
|
||||
print("Главное меню активно") # Лог при открытии меню
|
||||
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=TOP_PANEL_COLOR_USER, height=100)
|
||||
top_panel = tk.Frame(self.root, bg="#333333", height=100)
|
||||
top_panel.pack(fill=tk.X, side=tk.TOP)
|
||||
|
||||
# Кнопки на верхней панели
|
||||
for text, command in [("Профиль", self.show_profile), ("Магазин", self.show_shop), ("База знаний", self.show_knowledge)]:
|
||||
button = tk.Button(
|
||||
profile_button = tk.Button(
|
||||
top_panel,
|
||||
text=text,
|
||||
bg=BUTTON_COLOR_PROFILE_USER,
|
||||
fg=BUTTON_TEXT_COLOR_USER,
|
||||
font=FONT_USER,
|
||||
text="Профиль",
|
||||
bg="#555555",
|
||||
fg="white",
|
||||
font=FONT,
|
||||
relief=tk.FLAT,
|
||||
padx=20,
|
||||
pady=10,
|
||||
command=command,
|
||||
command=self.show_profile
|
||||
)
|
||||
button.pack(side=tk.LEFT, padx=20)
|
||||
profile_button.pack(side=tk.LEFT, padx=20)
|
||||
|
||||
# Кнопка "Играть" в центре
|
||||
play_button = tk.Button(
|
||||
self.root,
|
||||
text="Играть",
|
||||
bg=BUTTON_COLOR_PLAY_USER,
|
||||
fg=BUTTON_TEXT_COLOR_USER,
|
||||
font=BIG_FONT_USER,
|
||||
shop_button = tk.Button(
|
||||
top_panel,
|
||||
text="Магазин",
|
||||
bg="#555555",
|
||||
fg="white",
|
||||
font=FONT,
|
||||
relief=tk.FLAT,
|
||||
height=2,
|
||||
width=10,
|
||||
command=self.play_game,
|
||||
padx=20,
|
||||
pady=10,
|
||||
command=self.show_shop
|
||||
)
|
||||
play_button.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
|
||||
shop_button.pack(side=tk.LEFT, padx=20)
|
||||
|
||||
# Кнопка "Выход" в правом нижнем углу
|
||||
exit_button = tk.Button(
|
||||
self.root,
|
||||
text="Выход",
|
||||
bg=BUTTON_COLOR_EXIT_USER,
|
||||
fg=BUTTON_TEXT_COLOR_USER,
|
||||
font=FONT_USER,
|
||||
width=EXIT_BUTTON_SIZE_USER[0] // 10,
|
||||
height=EXIT_BUTTON_SIZE_USER[1] // 10,
|
||||
command=self.exit_app,
|
||||
knowledge_button = tk.Button(
|
||||
top_panel,
|
||||
text="База знаний",
|
||||
bg="#555555",
|
||||
fg="white",
|
||||
font=FONT,
|
||||
relief=tk.FLAT,
|
||||
padx=20,
|
||||
pady=10,
|
||||
command=self.show_knowledge
|
||||
)
|
||||
exit_button.place(relx=1.0, rely=1.0, x=-20, y=-20, anchor=tk.SE)
|
||||
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())
|
||||
|
||||
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):
|
||||
"""Показать экран профиля пользователя."""
|
||||
self.clear_frame()
|
||||
profile_ui(self.root, self.user_id) # Передаем user_id в profile_ui
|
||||
|
||||
def show_shop(self):
|
||||
"""Показать экран магазина."""
|
||||
self.clear_frame()
|
||||
shop_ui(self.root)
|
||||
|
||||
def show_knowledge(self):
|
||||
"""Показать базу знаний."""
|
||||
self.clear_frame()
|
||||
knowledge_ui(self.root)
|
||||
|
||||
def clear_frame(self):
|
||||
"""Очистить текущий экран."""
|
||||
for widget in self.root.winfo_children():
|
||||
widget.destroy()
|
||||
|
||||
def play_game(self):
|
||||
"""Заглушка для игры."""
|
||||
"""Переход к игровому интерфейсу."""
|
||||
clear_frame(self.root) # Очищаем главное меню
|
||||
GameUI(self.root, self.user_id) # Открываем игровой интерфейс
|
||||
print("Запуск игры...")
|
||||
|
||||
def exit_app(self):
|
||||
|
|
@ -80,14 +169,9 @@ class UserApp:
|
|||
print("Приложение закрыто")
|
||||
self.root.quit()
|
||||
|
||||
def show_profile(self):
|
||||
"""Заглушка для профиля."""
|
||||
print("Переход в профиль...")
|
||||
# Запуск главного окна
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
app = UserApp(root, user_id=123) # Передаем user_id (это может быть получено после авторизации)
|
||||
root.mainloop()
|
||||
|
||||
def show_shop(self):
|
||||
"""Заглушка для магазина."""
|
||||
print("Переход в магазин...")
|
||||
|
||||
def show_knowledge(self):
|
||||
"""Заглушка для базы знаний."""
|
||||
print("Переход в базу знаний...")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import tkinter as tk
|
||||
from src.utils import clear_frame
|
||||
from database.db_events import get_user_progress
|
||||
|
||||
|
||||
def profile_ui(root, user_id):
|
||||
"""Интерфейс профиля пользователя."""
|
||||
clear_frame(root)
|
||||
|
||||
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)
|
||||
|
||||
# Статистика пользователя
|
||||
progress = get_user_progress(user_id)
|
||||
levels_completed = len(progress)
|
||||
bones_collected = sum([session.score for session in progress])
|
||||
|
||||
stats_text = f"Пройдено уровней: {levels_completed}\nСобрано косточек: {bones_collected}"
|
||||
tk.Label(frame, text=stats_text, font=("Comic Sans MS", 20), bg="#f8e1e1").pack(pady=10)
|
||||
|
||||
tk.Button(frame, text="Назад", command=lambda: clear_frame(root), font=("Comic Sans MS", 20)).pack(pady=20)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import tkinter as tk
|
||||
from src.utils import clear_frame
|
||||
from database.db_events import get_dogs, update_user_dog
|
||||
|
||||
|
||||
def shop_ui(root, user_id):
|
||||
"""Интерфейс магазина."""
|
||||
clear_frame(root)
|
||||
|
||||
frame = tk.Frame(root, bg="#e5e5e5")
|
||||
frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
tk.Label(frame, text="Магазин", font=("Comic Sans MS", 30), bg="#e5e5e5").pack(pady=20)
|
||||
|
||||
dogs = get_dogs() # Получить список собак из базы данных
|
||||
for dog in dogs:
|
||||
dog_frame = tk.Frame(frame, bg="#f8f8f8", bd=2, relief=tk.RIDGE)
|
||||
dog_frame.pack(pady=5, padx=10, fill=tk.X)
|
||||
|
||||
tk.Label(dog_frame, text=dog.breed, font=("Comic Sans MS", 20), bg="#f8f8f8").pack(side=tk.LEFT, padx=10)
|
||||
tk.Button(dog_frame, text="Купить", command=lambda d=dog: update_user_dog(user_id, d.dog_id)).pack(
|
||||
side=tk.RIGHT, padx=10)
|
||||
|
||||
tk.Button(frame, text="Назад", command=lambda: clear_frame(root), font=("Comic Sans MS", 20)).pack(pady=20)
|
||||
BIN
src/user_functions/__pycache__/game_functions.cpython-313.pyc
Normal file
BIN
src/user_functions/__pycache__/map_generator.cpython-313.pyc
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
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)
|
||||
|
||||
# Начало уровня
|
||||
# Здесь подключается логика работы с картой и вопросами
|
||||
pass
|
||||
|
||||
|
||||
def handle_obstacle(obstacle, current_score, root):
|
||||
"""
|
||||
Обработка препятствия (вопроса) с использованием окна.
|
||||
Возвращает новый счёт игрока.
|
||||
"""
|
||||
result = {"new_score": current_score}
|
||||
|
||||
def submit_answer():
|
||||
user_answer = answer_var.get().strip().lower()
|
||||
if user_answer == "правильно": # Условие для правильного ответа
|
||||
result["new_score"] += 1
|
||||
else:
|
||||
result["new_score"] -= 1
|
||||
question_window.destroy() # Закрываем окно вопроса
|
||||
|
||||
# Создаём новое окно для вопроса
|
||||
question_window = tk.Toplevel(root)
|
||||
question_window.title("Вопрос")
|
||||
question_window.geometry("400x200")
|
||||
|
||||
# Отображение текста вопроса
|
||||
tk.Label(question_window, text=f"Вопрос сложности {obstacle['difficulty']}:", font=("Arial", 14)).pack(pady=10)
|
||||
|
||||
# Поле ввода ответа
|
||||
answer_var = tk.StringVar()
|
||||
tk.Entry(question_window, textvariable=answer_var, font=("Arial", 12)).pack(pady=10)
|
||||
|
||||
# Кнопка подтверждения ответа
|
||||
tk.Button(question_window, text="Ответить", command=submit_answer).pack(pady=10)
|
||||
|
||||
# Ожидаем закрытия окна
|
||||
question_window.grab_set() # Блокируем основное окно
|
||||
root.wait_window(question_window) # Ждём завершения окна вопроса
|
||||
|
||||
return result
|
||||
13
src/user_functions/map_generator.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import random
|
||||
|
||||
def generate_map(level):
|
||||
"""Генерация карты уровня."""
|
||||
num_obstacles = random.randint(3, 6)
|
||||
map_data = []
|
||||
for i in range(num_obstacles):
|
||||
map_data.append({
|
||||
"type": "question",
|
||||
"difficulty": level,
|
||||
"position": random.randint(1, 100)
|
||||
})
|
||||
return map_data
|
||||
22
src/utils.py
|
|
@ -1,4 +1,6 @@
|
|||
import tkinter as tk
|
||||
from tkinter import messagebox
|
||||
|
||||
|
||||
def clear_frame(frame):
|
||||
"""Удаление всех виджетов из фрейма."""
|
||||
|
|
@ -16,16 +18,10 @@ def feature_in_development(frame):
|
|||
font=("Comic Sans MS", 16)
|
||||
).pack(expand=True)
|
||||
|
||||
def create_tooltip(widget, text):
|
||||
"""Создание подсказки для виджета."""
|
||||
tooltip = tk.Toplevel()
|
||||
tooltip.wm_overrideredirect(True) # Отключаем рамки окна
|
||||
tooltip.wm_geometry(f"+{widget.winfo_rootx() + 20}+{widget.winfo_rooty() + 20}")
|
||||
label = tk.Label(tooltip, text=text, bg="#333", fg="#fff", font=("Comic Sans MS", 10), padx=5, pady=5)
|
||||
label.pack()
|
||||
|
||||
def hide_tooltip(event):
|
||||
tooltip.destroy()
|
||||
|
||||
widget.bind("<Enter>", lambda event: tooltip.deiconify())
|
||||
widget.bind("<Leave>", hide_tooltip)
|
||||
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)
|
||||