Зауважте: коли в LMS десятки курсів із різними форматами завдань — від есе до програмування — стандартна форма завантаження файлів перестає працювати. Викладачі витрачають години на перевірку, студенти плутаються в дедлайнах, а оцінки доводиться вручну переносити в журнал. Ми вирішили цю проблему для 50+ освітніх платформ, створивши модуль, який автоматизує перевірку завдань на всіх етапах: від здачі до фіксації оцінки.
Наша система підтримує шість типів відповідей, гнучкі дедлайни з прогресивним штрафом, множинні спроби та peer review. У цій статті — технічні деталі реалізації: модель даних, патерни безпеки під час завантаження файлів, алгоритми розрахунку оцінок і API для інтеграції. Ви отримаєте не просто модуль, а готове рішення з гарантією 6 місяців.
Проблеми, які вирішуємо
Стандартні системи управління навчанням (LMS) часто обмежені одним типом відповіді — текстовим полем. Для курсів програмування потрібен редактор коду, для дизайну — завантаження макетів, для групової роботи — взаємна перевірка. Без цього викладачі змушені використовувати сторонні сервіси, а студенти — перемикатися між вікнами. Наша система об'єднує все в одному інтерфейсі.
Типи завдань та їх реалізація
| Тип | Опис |
|---|---|
| Текстова відповідь | есе, теоретичні питання, розбір кейсів |
| Завантаження файлів | PDF, Word, архіви з кодом, зображення (до 50 МБ через presigned URLs) |
| Посилання на зовнішній ресурс | GitHub репозиторій, опублікований сайт, Google Docs |
| Онлайн-редактор коду | вбудований Monaco Editor з підсвічуванням синтаксису |
| Quiz | тестування з варіантами відповідей, автоматичною перевіркою та обмеженням за часом |
| Peer review | взаємна перевірка між студентами з анонімністю та критеріями оцінювання |
Як ми це робимо: технічний розбір
Модель даних завдань
CREATE TABLE assignments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
lesson_id UUID REFERENCES lessons(id),
course_id UUID REFERENCES courses(id),
title VARCHAR(500) NOT NULL,
description TEXT,
type VARCHAR(50) NOT NULL,
max_score INT NOT NULL DEFAULT 100,
deadline TIMESTAMPTZ,
late_submission BOOLEAN DEFAULT FALSE,
late_penalty INT DEFAULT 0,
max_attempts INT DEFAULT 1,
is_required BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE submissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
assignment_id UUID REFERENCES assignments(id),
student_id UUID REFERENCES users(id),
attempt_number INT NOT NULL DEFAULT 1,
status VARCHAR(50) DEFAULT 'draft',
text_answer TEXT,
file_urls JSONB DEFAULT '[]',
external_url VARCHAR(2000),
code_answer TEXT,
submitted_at TIMESTAMPTZ,
graded_at TIMESTAMPTZ,
score INT,
feedback TEXT,
UNIQUE(assignment_id, student_id, attempt_number)
);
Як забезпечується безпечне завантаження файлів?
Пряме завантаження через сервер — антипатерн для LMS з тисячами студентів. Ми використовуємо presigned URLs: браузер завантажує файл безпосередньо в S3/MinIO, минаючи наш бекенд. Це знижує навантаження на сервер і усуває вузьке місце. Порівняння: presigned URLs знижують навантаження на бекенд у 10 разів порівняно з прямим завантаженням.
async function getUploadUrl(assignmentId, fileName, fileSize, userId) {
if (fileSize > 50 * 1024 * 1024) {
throw new Error('File too large');
}
const allowedTypes = ['application/pdf', 'application/zip', 'image/png', 'image/jpeg'];
if (!allowedTypes.includes(mimeType)) {
throw new Error('File type not allowed');
}
const key = `submissions/${userId}/${assignmentId}/${uuid()}-${fileName}`;
const url = await s3.getSignedUrlPromise('putObject', {
Bucket: process.env.S3_BUCKET,
Key: key,
Expires: 300,
ContentType: mimeType,
ContentLength: fileSize,
});
return { uploadUrl: url, fileKey: key };
}
Автоматичне управління статусами та штрафами
Система проходить через ланцюжок статусів: draft → submitted → reviewing → graded. При відхиленні — статус returned з коментарем викладача і можливістю повторно відправити. На кожному переході надсилаються сповіщення (email, Telegram, in-app).
Пізня здача: якщо late_submission = true, завдання приймається після дедлайну, але оцінка автоматично знижується на late_penalty % за кожну добу. Максимальний штраф — 50 %. Якщо минуло більше тижня — автоматично 0 балів.
Алгоритм розрахунку оцінки з урахуванням штрафу
function calculateFinalScore(rawScore, submittedAt, deadline, latePenalty) {
if (submittedAt <= deadline) return rawScore;
const hoursLate = (submittedAt - deadline) / (1000 * 60 * 60);
if (hoursLate > 168) return 0;
const penalty = Math.min(latePenalty * Math.ceil(hoursLate / 24), 50);
return Math.round(rawScore * (1 - penalty / 100));
}
При max_attempts > 1 студент може повторно відправити завдання. Кожна спроба — окремий запис у submissions з інкрементованим attempt_number. До журналу оцінок передається найкращий результат з усіх спроб (або останній — налаштовується).
Детальний приклад: налаштування peer review
Peer review вмикається для завдання з типом peer_review. Налаштування проходить за кроками:
- Викладач створює завдання з типом
peer_reviewі задає критерії оцінювання (рубрикатор). - Після дедлайну система автоматично розподіляє анонімні роботи між студентами (кожну роботу перевіряють 2–3 студенти).
- Студенти перевіряють роботи та виставляють бали за критеріями.
- Підсумкова оцінка обчислюється як медіана всіх оцінок. Якщо оцінки розходяться більш ніж на 20 %, призначається додатковий рев'юер.
- Студент, який не перевірив вчасно, отримує штрафні бали.
Такий підхід скорочує час викладача на перевірку в 3 рази.
Інтеграція з вашою системою управління навчанням
Ми надаємо REST API та webhook-сповіщення для синхронізації з вашою LMS. Можлива інтеграція через LTI 1.3 або кастомні конектори. Архітектура дозволяє вбудувати модуль у будь-яку платформу — Moodle, Canvas, самописну систему. При використанні LTI 1.3 студенти та курси імпортуються автоматично, а оцінки передаються назад до журналу LMS.
Процес і терміни розробки
Що входить у роботу
- Повне проєктування — ER-діаграми, API-специфікація (OpenAPI)
- Фронтенд — React / Next.js з адаптивним дизайном та підтримкою сенсорних пристроїв
- Бекенд — Laravel / Node.js з PostgreSQL і Redis
- Інтеграція — LTI 1.3, REST API, webhooks для вашої LMS
- Документація — інструкції для викладачів і студентів
- Навантажувальне тестування — до 10 000 одночасних запитів
- Підтримка 1 місяць — безкоштовно після запуску
Типові терміни
| Тип завдання | Термін розробки |
|---|---|
| Базова система (текст, файли, статуси) | 5–7 днів |
| Додавання online-редактора коду (Monaco) | +3–4 дні |
| Quiz і автоматична перевірка | +3–5 днів |
| Peer review | +4–6 днів |
| Повний функціонал (все разом) | 10–14 днів |
Терміни варіюються залежно від складності інтеграції та кількості типів завдань. Оцінку за вашим проєктом даємо безкоштовно за 1 день.
Чому обирають нас?
- 10+ років на ринку розробки освітніх платформ
- 50+ впроваджень для вишів, онлайн-шкіл та корпоративних університетів
- Сертифіковані інженери Laravel, React, AWS
- Гарантія на код — 6 місяців
- Відкритість — передаємо вихідний код, міграції, CI/CD пайплайн
Зв'яжіться з нами для консультації — ми оцінимо ваш проєкт і запропонуємо оптимальне рішення. Замовте розробку під ключ і отримайте систему, яка реально спрощує перевірку завдань. Отримайте безкоштовну оцінку вашого проєкту за 1 день.







