+ статистика

+ логирование
исправить: уведомления (сломался софт)
This commit is contained in:
Xatiko 2024-11-21 01:01:03 +03:00
parent 5c2cbbbad0
commit e01f43dc35
13 changed files with 637 additions and 51 deletions

View file

@ -23,3 +23,6 @@ DATABASE_URL = "sqlite:///database/DogAcademy.db" # Обновлено на п
# Иконки # Иконки
SETTINGS_IMG = "assets/settings.png" SETTINGS_IMG = "assets/settings.png"
# Уровни уведомлений (для дальнейшей настройки)
NOTIFICATION_LEVEL = "info" # Возможные значения: "info", "warning", "error"

Binary file not shown.

View file

@ -1,5 +1,5 @@
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
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
def create_user(login, password): def create_user(login, password):
@ -26,3 +26,20 @@ def check_user(login, password):
return False return False
finally: finally:
session.close() session.close()
def log_db_event(event_message, root):
# Логирование события с базы данных
try:
# Пример добавления события в лог
with open('logs/database_logs.txt', 'a') as log_file:
log_file.write(event_message + "\n")
# Уведомление для администратора
notification = Notifications(root)
notification.show_info("Событие", f"Событие успешно записано: {event_message}")
except Exception as e:
# Если ошибка при записи в лог
notification = Notifications(root)
notification.show_error("Ошибка", f"Ошибка при записи в лог: {str(e)}")

View file

@ -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

View file

@ -1,5 +1,6 @@
from sqlalchemy import Column, Integer, String, ForeignKey, Text from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime
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()
@ -26,6 +27,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):
@ -47,9 +50,36 @@ class Questions(Base):
__tablename__ = 'questions' __tablename__ = 'questions'
question_id = Column(Integer, primary_key=True) question_id = Column(Integer, primary_key=True)
dog_id = Column(Integer, ForeignKey('dogs.dog_id')) dog_id = Column(Integer, ForeignKey('dogs.dog_id'))
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'
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()) # Исправлено
end_time = Column(DateTime, nullable=True)
# Связь с таблицей 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 - прочитано
# Связь с таблицей Users
user = relationship("Users", back_populates="notifications")

BIN
ishodniki/admin_panel.psd Normal file

Binary file not shown.

329
logs/logfile.log Normal file
View file

@ -0,0 +1,329 @@
2024-11-20 12:59:15 - BEGIN (implicit)
2024-11-20 12:59:15 - 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-20 12:59:15 - [generated in 0.00054s] ()
2024-11-20 12:59:15 - 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-20 12:59:15 - [generated in 0.00030s] ()
2024-11-20 13:00:56 - BEGIN (implicit)
2024-11-20 13:00:56 - PRAGMA main.table_info("auth")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA temp.table_info("auth")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA main.table_info("users")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA temp.table_info("users")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA main.table_info("dogs")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA temp.table_info("dogs")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA main.table_info("questions")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA temp.table_info("questions")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA main.table_info("game_sessions")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 - PRAGMA temp.table_info("game_sessions")
2024-11-20 13:00:56 - [raw sql] ()
2024-11-20 13:00:56 -
CREATE TABLE auth (
user_id INTEGER NOT NULL,
login VARCHAR NOT NULL,
password VARCHAR NOT NULL,
PRIMARY KEY (user_id),
UNIQUE (login)
)
2024-11-20 13:00:56 - [no key 0.00011s] ()
2024-11-20 13:00:56 -
CREATE TABLE dogs (
dog_id INTEGER NOT NULL,
breed VARCHAR,
characteristics TEXT,
behavior TEXT,
care_info TEXT,
admin_comments TEXT,
PRIMARY KEY (dog_id)
)
2024-11-20 13:00:56 - [no key 0.00017s] ()
2024-11-20 13:00:56 -
CREATE TABLE users (
user_id INTEGER NOT NULL,
dog_id INTEGER,
username VARCHAR NOT NULL,
level INTEGER,
achievement TEXT,
PRIMARY KEY (user_id),
FOREIGN KEY(user_id) REFERENCES auth (user_id),
FOREIGN KEY(dog_id) REFERENCES dogs (dog_id)
)
2024-11-20 13:00:56 - [no key 0.00019s] ()
2024-11-20 13:00:56 -
CREATE TABLE questions (
question_id INTEGER NOT NULL,
dog_id INTEGER,
question_text TEXT NOT NULL,
image_url VARCHAR,
helpful_info TEXT,
incorrect_attempts INTEGER,
PRIMARY KEY (question_id),
FOREIGN KEY(dog_id) REFERENCES dogs (dog_id)
)
2024-11-20 13:00:56 - [no key 0.00017s] ()
2024-11-20 13:00:57 -
CREATE TABLE game_sessions (
session_id INTEGER NOT NULL,
user_id INTEGER,
level INTEGER NOT NULL,
score INTEGER,
duration INTEGER,
start_time DATETIME,
end_time DATETIME,
PRIMARY KEY (session_id),
FOREIGN KEY(user_id) REFERENCES users (user_id)
)
2024-11-20 13:00:57 - [no key 0.00023s] ()
2024-11-20 13:00:57 - COMMIT
2024-11-20 13:01:13 - BEGIN (implicit)
2024-11-20 13:01:13 - 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-20 13:01:13 - [generated in 0.00032s] ()
2024-11-20 13:01:13 - 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-20 13:01:13 - [generated in 0.00025s] ()
2024-11-20 13:01:13 - 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-20 13:01:13 - [generated in 0.00028s] ()
2024-11-20 13:01:13 - SELECT avg(game_sessions.duration) AS avg_1
FROM game_sessions
2024-11-20 13:01:13 - [generated in 0.00023s] ()
2024-11-20 13:01:13 - ROLLBACK
2024-11-20 13:01:13 - BEGIN (implicit)
2024-11-20 13:01:13 - SELECT game_sessions.start_time AS game_sessions_start_time
FROM game_sessions
2024-11-20 13:01:13 - [generated in 0.00028s] ()
2024-11-20 13:01:13 - ROLLBACK
2024-11-20 13:40:04 - BEGIN (implicit)
2024-11-20 13:40:04 - PRAGMA main.table_info("auth")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA temp.table_info("auth")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA main.table_info("users")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA temp.table_info("users")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA main.table_info("dogs")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA temp.table_info("dogs")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA main.table_info("questions")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA temp.table_info("questions")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA main.table_info("game_sessions")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA temp.table_info("game_sessions")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA main.table_info("notifications")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 - PRAGMA temp.table_info("notifications")
2024-11-20 13:40:04 - [raw sql] ()
2024-11-20 13:40:04 -
CREATE TABLE auth (
user_id INTEGER NOT NULL,
login VARCHAR NOT NULL,
password VARCHAR NOT NULL,
PRIMARY KEY (user_id),
UNIQUE (login)
)
2024-11-20 13:40:04 - [no key 0.00011s] ()
2024-11-20 13:40:04 -
CREATE TABLE dogs (
dog_id INTEGER NOT NULL,
breed VARCHAR,
characteristics TEXT,
behavior TEXT,
care_info TEXT,
admin_comments TEXT,
PRIMARY KEY (dog_id)
)
2024-11-20 13:40:04 - [no key 0.00019s] ()
2024-11-20 13:40:04 -
CREATE TABLE users (
user_id INTEGER NOT NULL,
dog_id INTEGER,
username VARCHAR NOT NULL,
level INTEGER,
achievement TEXT,
PRIMARY KEY (user_id),
FOREIGN KEY(user_id) REFERENCES auth (user_id),
FOREIGN KEY(dog_id) REFERENCES dogs (dog_id)
)
2024-11-20 13:40:04 - [no key 0.00023s] ()
2024-11-20 13:40:04 -
CREATE TABLE questions (
question_id INTEGER NOT NULL,
dog_id INTEGER,
question_text TEXT NOT NULL,
image_url VARCHAR,
helpful_info TEXT,
incorrect_attempts INTEGER,
PRIMARY KEY (question_id),
FOREIGN KEY(dog_id) REFERENCES dogs (dog_id)
)
2024-11-20 13:40:04 - [no key 0.00020s] ()
2024-11-20 13:40:04 -
CREATE TABLE game_sessions (
session_id INTEGER NOT NULL,
user_id INTEGER,
level INTEGER NOT NULL,
score INTEGER,
duration INTEGER,
start_time DATETIME,
end_time DATETIME,
PRIMARY KEY (session_id),
FOREIGN KEY(user_id) REFERENCES users (user_id)
)
2024-11-20 13:40:04 - [no key 0.00020s] ()
2024-11-20 13:40:05 -
CREATE TABLE notifications (
notification_id INTEGER NOT NULL,
user_id INTEGER,
message TEXT NOT NULL,
timestamp DATETIME,
is_read INTEGER,
PRIMARY KEY (notification_id),
FOREIGN KEY(user_id) REFERENCES users (user_id)
)
2024-11-20 13:40:05 - [no key 0.00017s] ()
2024-11-20 13:40:05 - COMMIT
2024-11-20 17:07:30 - BEGIN (implicit)
2024-11-20 17:07:30 - PRAGMA main.table_info("auth")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA temp.table_info("auth")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA main.table_info("users")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA temp.table_info("users")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA main.table_info("dogs")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA temp.table_info("dogs")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA main.table_info("questions")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA temp.table_info("questions")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA main.table_info("game_sessions")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA temp.table_info("game_sessions")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA main.table_info("notifications")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 - PRAGMA temp.table_info("notifications")
2024-11-20 17:07:30 - [raw sql] ()
2024-11-20 17:07:30 -
CREATE TABLE auth (
user_id INTEGER NOT NULL,
login VARCHAR NOT NULL,
password VARCHAR NOT NULL,
PRIMARY KEY (user_id),
UNIQUE (login)
)
2024-11-20 17:07:30 - [no key 0.00010s] ()
2024-11-20 17:07:30 -
CREATE TABLE dogs (
dog_id INTEGER NOT NULL,
breed VARCHAR,
characteristics TEXT,
behavior TEXT,
care_info TEXT,
admin_comments TEXT,
PRIMARY KEY (dog_id)
)
2024-11-20 17:07:30 - [no key 0.00025s] ()
2024-11-20 17:07:30 -
CREATE TABLE users (
user_id INTEGER NOT NULL,
dog_id INTEGER,
username VARCHAR NOT NULL,
level INTEGER,
achievement TEXT,
PRIMARY KEY (user_id),
FOREIGN KEY(user_id) REFERENCES auth (user_id),
FOREIGN KEY(dog_id) REFERENCES dogs (dog_id)
)
2024-11-20 17:07:30 - [no key 0.00023s] ()
2024-11-20 17:07:30 -
CREATE TABLE questions (
question_id INTEGER NOT NULL,
dog_id INTEGER,
question_text TEXT NOT NULL,
image_url VARCHAR,
helpful_info TEXT,
incorrect_attempts INTEGER,
PRIMARY KEY (question_id),
FOREIGN KEY(dog_id) REFERENCES dogs (dog_id)
)
2024-11-20 17:07:30 - [no key 0.00019s] ()
2024-11-20 17:07:30 -
CREATE TABLE game_sessions (
session_id INTEGER NOT NULL,
user_id INTEGER,
level INTEGER NOT NULL,
score INTEGER,
duration INTEGER,
start_time DATETIME,
end_time DATETIME,
PRIMARY KEY (session_id),
FOREIGN KEY(user_id) REFERENCES users (user_id)
)
2024-11-20 17:07:30 - [no key 0.00038s] ()
2024-11-20 17:07:30 -
CREATE TABLE notifications (
notification_id INTEGER NOT NULL,
user_id INTEGER,
message TEXT NOT NULL,
timestamp DATETIME,
is_read INTEGER,
PRIMARY KEY (notification_id),
FOREIGN KEY(user_id) REFERENCES users (user_id)
)
2024-11-20 17:07:30 - [no key 0.00018s] ()
2024-11-20 17:07:30 - COMMIT

View file

@ -2,22 +2,45 @@ import tkinter as tk
from tkinter import ttk from tkinter import ttk
import csv import csv
from src.utils import clear_frame 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): def show_logs(frame):
"""Отображение логов действий пользователей.""" """Отображение логов действий пользователей в тёмной теме."""
clear_frame(frame) clear_frame(frame)
tk.Label(frame, text="Логи действий", font=("Comic Sans MS", 16)).pack() 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") # Настройка таблицы с логами
table = ttk.Treeview(frame, columns=("Время", "Действие", "Пользователь"), show="headings", style="Dark.Treeview")
table.heading("Время", text="Время") table.heading("Время", text="Время")
table.heading("Действие", text="Действие") table.heading("Действие", text="Действие")
table.heading("Пользователь", text="Пользователь") table.heading("Пользователь", text="Пользователь")
table.pack(fill="both", expand=True) table.pack(fill="both", expand=True)
# Добавьте логи для примера # Добавление логов для примера
table.insert("", "end", values=("2024-11-19 12:30", "Добавление вопроса", "admin")) table.insert("", "end", values=("2024-11-19 12:30", "Добавление вопроса", "admin"))
table.insert("", "end", values=("2024-11-19 13:00", "Удаление пользователя", "moderator")) 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(): def export_logs():
data = [ data = [

View file

@ -1,7 +1,7 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from database.models import Questions from database.models import Questions, Notifications
from database.db_session import engine from database.db_session import engine
from src.utils import clear_frame from src.utils import clear_frame
@ -34,3 +34,19 @@ def manage_questions(frame):
table.insert("", "end", values=(question.id, question.text, question.answer)) table.insert("", "end", values=(question.id, question.text, question.answer))
session.close() session.close()
def add_user_to_db(user_data, root):
# Логика добавления пользователя в базу данных
try:
# Пример кода для добавления в базу (зависит от реализации вашей базы данных)
# db_session.add(user_data)
# db_session.commit()
# Если добавление прошло успешно
notification = Notifications(root)
notification.show_info("Успех", f"Пользователь {user_data['username']} успешно добавлен!")
except Exception as e:
# Если возникла ошибка
notification = Notifications(root)
notification.show_error("Ошибка", f"Ошибка при добавлении пользователя: {str(e)}")

View file

@ -0,0 +1,21 @@
from tkinter import messagebox
class Notification:
def __init__(self, root):
self.root = root
def show_info(self, title, message):
"""Отображение информационного уведомления"""
messagebox.showinfo(title, message)
def show_warning(self, title, message):
"""Отображение предупреждения"""
messagebox.showwarning(title, message)
def show_error(self, title, message):
"""Отображение ошибки"""
messagebox.showerror(title, message)
def show_notification(self, title, message):
"""Отображение общего уведомления"""
self.show_info(title, message)

View file

View file

@ -3,22 +3,96 @@ from tkinter import ttk
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from src.utils import clear_frame 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): def show_statistics(frame):
"""Отображение статистики пользователей и уровней.""" """Отображение статистики."""
clear_frame(frame) clear_frame(frame)
tk.Label(frame, text="Статистика пользователей", font=("Comic Sans MS", 16)).pack() tk.Label(frame, text="Статистика", font=("Comic Sans MS", 16), bg="#403d49", fg="#b2acc0").pack(pady=10)
# Пример: график с количеством пользователей # Таблица с общей статистикой
fig, ax = plt.subplots() table = ttk.Treeview(frame, columns=("Metric", "Value"), show="headings", height=5)
ax.bar(["Level 1", "Level 2", "Level 3"], [10, 15, 8]) # Пример данных table.heading("Metric", text="Параметр")
ax.set_title("Популярность уровней") table.heading("Value", text="Значение")
ax.set_xlabel("Уровни") table.pack(pady=10, padx=20, fill="x", expand=True)
ax.set_ylabel("Количество прохождений")
# Получение данных для таблицы
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 = FigureCanvasTkAgg(fig, master=frame)
canvas.get_tk_widget().pack(fill="both", expand=True) canvas.get_tk_widget().pack(fill="both", expand=True)
canvas.draw() 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

View file

@ -3,6 +3,9 @@ from PIL import Image, ImageTk
from config import SETTINGS_IMG from config import SETTINGS_IMG
from src.admin_functions import db_management, admin_logging, statistics, content, knowledge_base from src.admin_functions import db_management, admin_logging, statistics, content, knowledge_base
from src.utils import clear_frame # Импортируем общую функцию для очистки фрейма from src.utils import clear_frame # Импортируем общую функцию для очистки фрейма
from database.db_session import get_session
from database.models import Notifications
from src.admin_functions.notification import Notification
# Конфигурация цветов из config.py # Конфигурация цветов из config.py
@ -14,12 +17,26 @@ MENU_COLOR = "#2f2b38"
MENU_OPACITY = 0.9 # Прозрачность меню MENU_OPACITY = 0.9 # Прозрачность меню
class AdminApp: class AdminApp:
def __init__(self, root): def __init__(self, root, master):
self.root = root self.root = root
self.master = master
self.root.title("Админ-Панель") self.root.title("Админ-Панель")
self.root.geometry("1920x1080") self.root.geometry("1920x1080")
self.root.config(bg=BACKGROUND_COLOR) self.root.config(bg=BACKGROUND_COLOR)
self.notification = Notification(self.master)
def edit_database(self):
# Логика редактирования базы данных
# Например, успешное редактирование
self.notification.show_info("Успех", "База данных успешно обновлена!")
def show_error(self, message):
self.notification.show_error("Ошибка", message)
def show_warning(self, message):
self.notification.show_warning("Предупреждение", message)
# Верхняя панель # Верхняя панель
self.top_bar = tk.Frame(self.root, bg=TOP_BAR_COLOR, height=60) self.top_bar = tk.Frame(self.root, bg=TOP_BAR_COLOR, height=60)
self.top_bar.pack(side="top", fill="x") self.top_bar.pack(side="top", fill="x")
@ -71,43 +88,94 @@ class AdminApp:
def toggle_menu(self): def toggle_menu(self):
"""Показ или скрытие меню.""" """Показ или скрытие меню."""
print( if self.menu_visible:
f"Кнопка меню нажата. Меню сейчас {'видимо' if self.menu_visible else 'скрыто'}") # Отладка self.menu_frame.lower()
if self.menu_visible: # Используем флаг для проверки состояния
print("Скрываем меню") # Отладка
self.menu_frame.lower() # Скрываем меню
self.menu_visible = False self.menu_visible = False
else: else:
print("Показываем меню") # Отладка self.menu_frame.lift()
self.menu_frame.lift() # Показываем меню
self.menu_visible = True self.menu_visible = True
self.populate_menu() # Наполнение меню элементами self.populate_menu()
def populate_menu(self): def populate_menu(self):
# Очистка меню # Очистка меню
for widget in self.menu_frame.winfo_children(): for widget in self.menu_frame.winfo_children():
widget.destroy() widget.destroy()
# Создание пунктов меню
self.create_menu_section("Работа с базой данных", [ # Список разделов и их элементов
menu_sections = [
("Работа с базой данных", [
("Редактирование пользователей", db_management.edit_users), ("Редактирование пользователей", db_management.edit_users),
("Управление вопросами", db_management.manage_questions), ("Управление вопросами", db_management.manage_questions),
("Просмотр таблиц", db_management.view_tables), ("Просмотр таблиц", db_management.view_tables),
]) ]),
self.create_menu_section("Управление игровым контентом", [ ("Управление игровым контентом", [
("Создание и настройка уровней", content.manage_levels), ("Создание и настройка уровней", content.manage_levels),
("Настройка параметров собаки", content.manage_dog_params), ("Настройка параметров собаки", content.manage_dog_params),
]) ]),
self.create_menu_section("Управление интерфейсом пользователя", [ ("Управление интерфейсом пользователя", [
("Изменение цветовой схемы, фона и логотипа", self.change_ui_settings),
("Добавление подсказок в интерфейс", self.manage_ui_tips), ("Добавление подсказок в интерфейс", self.manage_ui_tips),
]) ]),
self.create_menu_section("Работа с базой знаний", [ ("Работа с базой знаний", [
("Добавление информации", knowledge_base.add_info), ("Добавление информации", knowledge_base.add_info),
("Редактирование записей", knowledge_base.edit_records), ("Редактирование записей", knowledge_base.edit_records),
("Удаление записей", knowledge_base.delete_records), ("Удаление записей", knowledge_base.delete_records),
("Просмотр базы знаний", knowledge_base.view_knowledge_base), ("Просмотр базы знаний", knowledge_base.view_knowledge_base),
("Генерация вопросов", knowledge_base.generate_questions), ("Генерация вопросов", knowledge_base.generate_questions),
]) ]),
]
# Определяем максимальную ширину текста для настройки ширины меню и кнопок
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"),
anchor="center" # Выравнивание по центру
)
section_label.pack(fill="x", padx=10, pady=5)
total_height += button_height + section_spacing
# Кнопки раздела
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),
width=int(menu_width / 10) - 3, # Ширина кнопок зависит от ширины меню
height=1,
activebackground=BUTTON_COLOR,
activeforeground=TEXT_COLOR,
bd=0,
anchor="w", # Выравнивание текста по левому краю
command=lambda: command(self.main_frame) # Вызываем функцию и передаём фрейм
)
item_button.pack(fill="x", padx=20, pady=5)
total_height += button_height + button_spacing
# Подстройка высоты меню
self.menu_frame.config(height=total_height)
def create_menu_section(self, title, items): def create_menu_section(self, title, items):
section_label = tk.Label(self.menu_frame, text=title, bg=MENU_COLOR, fg=TEXT_COLOR, font=("Comic Sans MS", 14, "bold")) section_label = tk.Label(self.menu_frame, text=title, bg=MENU_COLOR, fg=TEXT_COLOR, font=("Comic Sans MS", 14, "bold"))
@ -150,8 +218,14 @@ class AdminApp:
tk.Label(frame, text="Здесь будут подсказки для интерфейса", bg=BACKGROUND_COLOR, fg=TEXT_COLOR, font=("Comic Sans MS", 16)).pack() tk.Label(frame, text="Здесь будут подсказки для интерфейса", bg=BACKGROUND_COLOR, fg=TEXT_COLOR, font=("Comic Sans MS", 16)).pack()
def show_notifications(self, frame): def show_notifications(self, frame):
clear_frame(frame) clear_frame(frame) # Очищаем текущий экран
tk.Label(frame, text="Здесь будут уведомления", bg=BACKGROUND_COLOR, fg=TEXT_COLOR, font=("Comic Sans MS", 16)).pack() session = get_session()
notifications = session.query(Notifications).filter_by(
is_read=0).all() # Получаем все непрочитанные уведомления
for notification in notifications:
tk.Label(frame, text=notification.message, bg=BACKGROUND_COLOR, fg=TEXT_COLOR,
font=("Comic Sans MS", 16)).pack()
session.close()
def show_security(self, frame): def show_security(self, frame):
clear_frame(frame) clear_frame(frame)