Files
LMS/README.md
2026-09-10 01:12:24 +03:00

118 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LMS: практические занятия по курсу «Промышленное программирование на C»
Минимальное ядро: регистрация, списки студентов, варианты лабораторных и их
распределение. Условие своего варианта студент видит в личном кабинете.
Два микросервиса:
- **lms-api** (`src/backend/lms_api`, :8000) — данные и логика (SQLite), REST `/api/v1`;
- **lms-web** (`src/frontend/lms_web`, :8080) — веб-интерфейс, ходит в API по HTTP.
## Запуск
```bash
make install # .venv + зависимости
make dev # lms-api :8000 + lms-web :8080
# открыть http://127.0.0.1:8080 — при первом запуске создать аккаунт преподавателя
```
Тесты: `make test` (11 проверок, свои порты/БД). В Docker: `make build && make up`
(или `make deploy`); данные — в volume `lms_data`.
## Возможности сейчас
**Преподаватель**
- аккаунт администратора (единственный), смена пароля;
- **Лабораторные** — создаются из JSON-файла с вариантами (см. `examples/lab1.json`):
`variants` с `level: main/advanced`, номером, условием, примерами и указаниями;
если срок сдачи в JSON не задан — автоматически ставится через 25 дней
(3 недели и 4 дня) после создания;
- **Группы** — импорт списков из `.xls/.xlsx` (название из шапки, столбцы:
№ п/п, студенческий номер, ФИО, основа обучения); новым студентам генерируется
пароль (логин = номер студенческого), выгрузка «ФИО, логин, пароль» (xlsx/csv),
сброс пароля;
- **Распределение вариантов**: студенту выбирается уровень (основная /
повышенная), затем по группе раздаются варианты конкретной лабораторной
(уникальны внутри группы, по возможности — между группами; если вариантов
меньше студентов — допустимы повторы), есть ручное назначение номера.
**Студент**
- вход по номеру студенческого и паролю; при первом входе смена пароля обязательна;
- список работ и условие своего варианта (по каждой работе — с примерами
входов/выходов и указаниями).
Остальное (отправка решений, задания на защиту/добор, тренировочные задачи,
оценки) будет добавлено позднее.
## Формат JSON лабораторной (`examples/lab1.json`)
```json
{
"number": 1,
"title": "Одномерные массивы и последовательности",
"semester": "осень",
"deadline": "2026-10-01T23:59",
"points_max": 5,
"goal": "…", "common_requirements": "…",
"variants": [
{ "level": "main", "number": "1", "statement": "…",
"examples": [ { "input": "4\n1 2 3 4", "output": "10", "explanation": "…" } ],
"notes": "…" },
{ "level": "advanced", "number": "21", "statement": "…" }
]
}
```
## Деплой на сервер
### Вариант 1 — Docker (рекомендую)
```bash
# на сервере: скопировать проект, затем
cp .env.example .env
nano .env # FRONTEND_PORT=8080 (или 80), API_PORT=8000
./deploy.sh # соберёт образы и поднимет сервисы
docker compose ps # статус
docker compose logs -f # логи
```
Данные (БД и загрузки) хранятся в volume `lms_data` — переживают перезапуск
и пересборку. Бэкап одной командой:
`docker run --rm -v lms_lms_data:/data -v $PWD:/backup alpine tar czf /backup/lms-backup.tar.gz /data`
Порты для наружу: пользователям нужен только `lms-web` (по умолчанию `:8080`).
`lms-api` достаточно оставить внутри сети compose (в `.env` не публиковать
`API_PORT`, либо ограничить доступ файрволом).
Если после обновления кода контейнер api падает с
`PermissionError: ... '/data/uploads'` (старый том создан от root) — сбросьте том
один раз и перезапустите (данных в нём ещё нет):
```bash
sudo docker compose down -v
sudo ./deploy.sh
```
### Вариант 2 — без Docker (процессы через systemd)
```bash
make install
# два юнита (пример /etc/systemd/system/lms-api.service):
# ExecStart=/path/to/lms/.venv/bin/python -m uvicorn lms_api.main:app
# --app-dir /path/to/lms/src/backend --host 0.0.0.0 --port 8000
# Environment=LMS_API_URL=http://127.0.0.1:8000
# и аналогично lms-web на --host 0.0.0.0 --port 8080 (lms_web.main:app, src/frontend)
```
Удобно поставить `lms-web` за nginx (HTTPS, отдача статики проксируется на :8080),
доступ к `/api/v1/*` на :8080 не требуется наружу.
## Структура
```
src/backend/lms_api/ # API: core/{db,security,variants,xls_import}, routers
src/frontend/lms_web/ # веб: routers, templates, static
tests/smoke_test.py # make test
examples/ # ПИ-11БО.xls, ПИ-12БО.xls, lab1.json
Dockerfile docker-compose.yml deploy.sh Makefile data/
```