# 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`, либо ограничить доступ файрволом). ### Вариант 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/ ```