Диаграммы классов - gogafefe/StAlGoLM GitHub Wiki

Диаграммы классов клиента и сервера

Диаграммы построены по текущему исходному коду проекта. Добавлять новые классы для их создания не требуется: диаграмма описывает уже существующую архитектуру.

Обозначения связей:

  • A <|-- B — класс B наследуется от A;
  • A *-- B — композиция: объект A владеет объектом или набором объектов B;
  • A --> B — направленная ассоциация;
  • A ..> B — зависимость: A использует B.

Клиент

В клиентской части собственный класс проекта один — MainWindow. Он наследуется от QMainWindow, создаёт TCP-сокет и элементы интерфейса Qt. Через сокет окно отправляет текстовые команды серверу и получает ответы.

Диаграмма классов клиента

Исходник Mermaid диаграммы клиента
classDiagram
    direction LR

    class QMainWindow
    class QTcpSocket
    class QLineEdit
    class QSpinBox
    class QPushButton
    class QComboBox
    class QButtonGroup
    class QPlainTextEdit
    class QLabel

    class MainWindow {
        -QTcpSocket socket
        -QLineEdit editHost
        -QSpinBox spinPort
        -QLineEdit editLogin
        -QLineEdit editPassword
        -QLineEdit editEmail
        -QComboBox comboTask
        -QSpinBox spinTaskNum
        -QButtonGroup optGroup
        -QLineEdit editAnswer
        -QPlainTextEdit logView
        -QLabel lblUser
        -bool loggedIn
        -int activeTaskType
        +MainWindow(parent)
        -buildUi()
        -sendCommand(command)
        -log(who, text)
        -setConnectionState(connected)
        -setRadiosEnabled(on)
        -resetTaskState()
        -onConnectClicked()
        -onConnected()
        -onDisconnected()
        -onReadyRead()
        -onSocketErrorOccurred(error)
        -onRegClicked()
        -onAuthClicked()
        -onLogoutClicked()
        -onWhoamiClicked()
        -onGetTaskClicked()
        -onAnswerClicked()
        -onMystatsClicked()
    }

    QMainWindow <|-- MainWindow : наследование
    MainWindow *-- QTcpSocket : TCP-соединение
    MainWindow *-- QLineEdit : поля ввода
    MainWindow *-- QSpinBox : числовые поля
    MainWindow *-- QPushButton : команды интерфейса
    MainWindow *-- QComboBox : выбор задания
    MainWindow *-- QButtonGroup : варианты ответа
    MainWindow *-- QPlainTextEdit : журнал обмена
    MainWindow *-- QLabel : состояние пользователя
Loading

Сервер

Серверная часть разделена на приём TCP-соединений, хранение состояния сессии, разбор команд, работу с базой данных и генерацию заданий. MyTcpServer и DatabaseManager реализованы как одиночки: получить их экземпляры можно через getInstance(), а копирование запрещено.

CommandFunctions и TaskGenerators на диаграмме отмечены стереотипом module. Это не классы C++, а логические группы свободных функций из файлов server_functions.* и task1.*–task4.*. Такое обозначение позволяет показать важные зависимости, не выдавая функции за реально существующие классы.

Диаграмма классов сервера

Исходник Mermaid диаграммы сервера
classDiagram
    direction LR

    namespace Qt {
        class QObject
        class QTcpServer
        class QTcpSocket
        class QSqlDatabase
    }

    class MyTcpServer {
        -QTcpServer mTcpServer
        -Map sessions
        -Map buffers
        -MyTcpServer(parent)
        -MyTcpServer(copy) deleted
        +getInstance() MyTcpServer*
        +~MyTcpServer()
        +slotNewConnection()
        +slotClientDisconnected()
        +slotServerRead()
    }

    class UserSession {
        +QString login
        +QString email
        +UserRole role
        +QTcpSocket msock
        +int currentTaskType
        +int currentTaskNum
        +int currentCorrectAnswer
    }

    class DatabaseManager {
        -QSqlDatabase db
        -DatabaseManager()
        -DatabaseManager(copy) deleted
        -initDatabase()
        -initStatisticTables()
        -updateLastAuth(login)
        +getInstance() DatabaseManager*
        +regUser(login, password, email, role) bool
        +authUserWithRole(login, password) UserRole
        +getUserRole(login) UserRole
        +getUserEmail(login) QString
        +deleteUser(login) bool
        +updateUserRole(login, role) bool
        +userExists(login) bool
        +getAllUsers() UserInfo[]
        +getStats() UserStats
        +createStatisticRows(login) bool
        +updateStatistic(login, task, problem, delta) bool
        +getStatisticRow(login, task) int[]
        +deleteStatisticRows(login) bool
    }

    class UserRole {
        <<enumeration>>
        ROLE_USER
        ROLE_MODERATOR
        ROLE_ADMIN
        ROLE_ERR
    }

    class UserInfo {
        +QString login
        +QString email
        +UserRole role
        +QString registeredAt
        +QString lastAuth
    }

    class UserStats {
        +int totalUsers
        +int newUsersMonth
        +int activeUsersMonth
    }

    class CommandFunctions {
        <<module>>
        +processCommand(command, session) QString
        +cmd_reg(parts) QString
        +cmd_auth(parts, session) QString
        +cmd_logout(session) QString
        +cmd_whoami(session) QString
        +cmd_del(parts, session) QString
        +cmd_role(parts, session) QString
        +cmd_users(session) QString
        +cmd_stats(session) QString
        +cmd_help() QString
        +cmd_task(type, number, session) QString
        +cmd_answer(answer, session) QString
        +cmd_mystats(parts, session) QString
    }

    class TaskGenerators {
        <<module>>
        +task1_generate(number) Task1Problem
        +task2_generate(number) Task2Problem
        +task3_generate(number) Task3Problem
        +task4_generate(number) Task4Problem
    }

    class Task1Problem {
        +QString text
        +int correctAnswer
    }
    class Task2Problem {
        +QString text
        +int correctAnswer
    }
    class Task3Problem {
        +QString text
        +int correctAnswer
    }
    class Task4Problem {
        +QString text
        +int correctAnswer
    }

    QObject <|-- MyTcpServer : наследование
    MyTcpServer *-- QTcpServer : владеет
    QTcpServer ..> QTcpSocket : принимает соединения
    MyTcpServer *-- UserSession : хранит сессии
    UserSession --> QTcpSocket : сокет клиента
    UserSession --> UserRole : роль
    MyTcpServer ..> CommandFunctions : передаёт команды
    CommandFunctions ..> UserSession : изменяет
    CommandFunctions ..> DatabaseManager : использует
    CommandFunctions ..> TaskGenerators : запрашивает задания
    DatabaseManager *-- QSqlDatabase : соединение SQLite
    DatabaseManager ..> UserRole : использует
    DatabaseManager ..> UserInfo : возвращает
    DatabaseManager ..> UserStats : возвращает
    TaskGenerators ..> Task1Problem : создаёт
    TaskGenerators ..> Task2Problem : создаёт
    TaskGenerators ..> Task3Problem : создаёт
    TaskGenerators ..> Task4Problem : создаёт
Loading

Что видно из диаграмм

  • Клиент отвечает только за интерфейс и обмен командами по TCP; вычисления заданий и работа с базой находятся на сервере.
  • Сервер хранит отдельную UserSession для каждого подключённого клиента.
  • Разбор команд связывает сетевой слой с базой данных и генераторами четырёх типов заданий.
  • Реализованный вариант № 3 не добавляет новый класс: он использует существующую структуру Task3Problem и функцию task3_generate().

Исходники Mermaid приведены выше; изображения PNG содержат редактируемые данные draw.io.

⚠️ **GitHub.com Fallback** ⚠️