@startuml !define primary_key(x) <&key> x !define foreign_key(x) <&key> x !define column(x) <&media-record> x !define table(x) entity x << (T, white) >> ' left to right direction title "Entity Relationship Diagram (ERD): exam (пополнение и провера знаний)" ' Аккаунты пользователей table(account) #eaa { primary_key(id): LONGSERIAL >>"Идентификатор" column(code): String >>"35-ичный код (логин)" foreign_key(orgstructure_id): LONGSERIAL >>"идентификатор места работы" } ' Оргструктура table(orgstructure) #eaa { primary_key(id): LONGSERIAL >>"Идентификатор" foreign_key(organization_id): LONGSERIAL>>"Идентификатор организации" foreign_key(position_id): LONGSERIAL>>"Идентификатор должности" } orgstructure --{ account ' Организации table(organization) #eaa { primary_key(id): LONGSERIAL >>"Идентификатор" column(name): STRING >>"Наименование" } organization --{ orgstructure ' Должности table(position) #eaa { primary_key(id): LONGSERIAL >>"Идентификатор" column(name): STRING >>"Наименование" } position --{ orgstructure ' Курсы ' По идентификатору курса определяется положение соответствующего курса ' в файловой системе сервиса table(course){ primary_key(id): LONGSERIAL >>"Идентификатор" column(name): STRING >>"Наименование" column(short): STRING >>"Сокращенно" } note top Не понятно, стоит ли хранить в базе пути до контента курса, или достаточно создавать курсы в виде статических директорий Если курс состоит из тем, где будет определен порядок представления тем пользователю end note ' тема table(theme){ primary_key(id): LONGSERIAL >>"Идентификатор" column(name): STRING >>"Наименование" ' foreign_key(course_id):LONGSERIAL >>"ID курса" } note top Курс может состоять из одной или нескольких тем тема определяет состав вопросов, которые смогут попасть в опрос по курсу Само тело курса также возможно разбить на отдельные темы, материал по которым будет оформляться в отдельных *.md файлах end note ' course --{ theme ' порядок расположения тем в курсе table(scheme){ primary_key(id): LONGSERIAL >>"Идентификатор" foreign_key(course_id): LONGSERIAL >>"Идентификатор курса" foreign_key(theme_id): LONGSERIAL >>"Идентификатор темы" column(position) INTEGER >>"Порядковый номер темы в курсе" } note top Схема курса определяет последовательность размещения тем в курсе end note course --{ scheme theme --{ scheme ' Список задач table(target) #eaa { primary_key(id): LONGSERIAL >>"Идентификатор задачи" foreign_key(orgstructure_id): LONGSERIAL >>"Идентификатор категории должности" foreign_key(course_id): LONGSERIAL >>"Идентификатор курса" column(questions_count): INTEGER >>"Количество вопросов для тестирования" column(limit): INTEGER >>"Количество вопросов, для успешного завершения опроса" } note top Тут формируется перечень назначенных пользователю курсов, на основании наименования организации и должности работника Тут определено общее количество вопросов для тестирвоания, далее вопросы берутся случайным образом из тем, относящихся к курсу в равных пропорциях end note orgstructure --{ target course --{ target ' Вопросы table(question){ primary_key(id): LONGSERIAL >>"Идентификатор вопроса" column(body): String >>"Содержание вопроса" foreign_key(theme_id): LONGSERIAL >>"Идентификатор темы вопроса" } theme --{ question table(answer){ primary_key(id): LONGSERIAL >>"Идентификатор ответа" column(body): STRING >>"Содержание ответа" foreign_key(question_id): LONGSERIAL >>"Идентификатор вопроса" column(status): BOOLEAN >>"статус ответа: верно / не верно" column(description): STRING >>"Пояснения, обоснование ответа" } question --{ answer ' Опрос table(quiz) #88f { primary_key(id): LONGSERIAL >>"Идентификатор опроса" foreign_key(account_id): LONGSERIAL >>"Идентификатор аккаунта" foreign_key(target_id): LONGSERIAL >>"Идентификатор задания" foreign_key(question_id): LONGSERIAL >>"Назначенный вопрос" foreign_key(answer_id): LONGSERIAL >>"Идентификатор данного ответа" column(datetime): DATETIME >>"Дата и время ответа" } question --{ quiz target --{ quiz account --{ quiz answer --{ quiz ' Результаты table(results) #88f { primary_key(id): LONGSERIAL >>"Идентификатор опроса" foreign_key(account_id): LONGSERIAL >>"Идентификатор аккаунта" foreign_key(target_id): LONGSERIAL >>"Идентификатор задания" column(status): BOOLEAN >>"сдано / не сдано" column(passed): DATETIME >>"Дата завершения" } note top Запись в таблицу результатов происходит по клику кнопки в графическом интерфейсе пишется время клика и пересчитываются правильные отвты end note quiz --{ results account -down-{ results @enduml