118 lines
6.1 KiB
Markdown
118 lines
6.1 KiB
Markdown
# 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/
|
||
```
|