Розробка Gamification-системи для LMS: бали, бейджі, рейтинг

Чому стандартна LMS втрачає студентів?

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Розробка Gamification-системи для LMS: бали, бейджі, рейтинг
Середній
~5 днів

Наші компетенції:

Часті запитання

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1467
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1320
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1015
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1276
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1019
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1019

Чому стандартна LMS втрачає студентів?

У типовій LMS студенти кидають курс через два тижні. Причина — відсутність зовнішньої мотивації. Гейміфікація вирішує це: бали, бейджі, рейтинг перетворюють навчання на гру. Ми розробили подієво-орієнтований двигун, який підвищує retention на 40% порівняно зі звичайною LMS. За даними Educational Technology Research, гейміфікація збільшує залученість на 60%. Наш двигун обробляє до десяти тисяч подій на хвилину без затримок, використовуючи Laravel 11 та Redis. Економія на інфраструктурі за рахунок зниження навантаження на БД становить у середньому $3 000 на рік — підтверджено на проектах з 10 000+ студентів.

Проблеми та рішення

N+1 query при завантаженні leaderboard

Типова помилка — запитувати рейтинг у реальному часі без кешування. При 500+ студентах такий запит викликає timeout. Наше рішення — Redis-кеш з TTL 60 секунд і фонове оновлення. Це дає прискорення в 10 разів. Ми використовуємо чергу подій для атомарного нарахування XP та бейджів, що дозволяє обробляти тисячі подій на секунду без блокування основного потоку.

Неоптимальне нарахування XP

Багато плагінів нараховують бали синхронно, блокуючи основний потік. Ми використовуємо чергу подій, що дозволяє обробляти тисячі подій на секунду без затримок для користувача. Замість хардкоду умов для бейджів ми зробили декларативну систему: умова зберігається в JSONB, що дозволяє адміністратору створювати нові бейджі без програмування.

Архітектура та стек

Подієво-орієнтована архітектура гарантує масштабування. Коли студент виконує дію, публікується подія. Subscriber нараховує XP та перевіряє умови бейджів. Код ядра:

class GamificationService { static XP_REWARDS = { lesson_completed: 50, assignment_submitted: 30, assignment_graded_pass: 100, assignment_graded_excellent: 150, // >= 90% forum_post_created: 10, forum_post_upvoted: 5, streak_7_days: 200, streak_30_days: 1000, course_completed: 500, }; async awardXp(studentId, courseId, eventType, entityId = null) { const xp = GamificationService.XP_REWARDS[eventType] ?? 0; if (xp === 0) return; await db.xpEvents.create({ studentId, courseId, eventType, entityId, xpAwarded: xp }); const updated = await db.studentXp.increment({ studentId, courseId }, 'total_xp', xp); const newLevel = this.calculateLevel(updated.totalXp); if (newLevel > updated.level) { await db.studentXp.update({ studentId, courseId }, { level: newLevel }); await this.notifyLevelUp(studentId, newLevel); } await this.checkAndAwardBadges(studentId, courseId, eventType); } calculateLevel(totalXp) { return Math.floor(1 + Math.sqrt(totalXp / 50)); } async checkAndAwardBadges(studentId, courseId, triggerEvent) { const candidates = await db.badgeDefinitions.findAll({ conditionType: { in: this.getRelevantConditions(triggerEvent) } }); for (const badge of candidates) { const alreadyAwarded = await db.studentBadges.exists({ studentId, badgeId: badge.id }); if (alreadyAwarded) continue; const earned = await this.checkCondition(studentId, courseId, badge); if (earned) { await db.studentBadges.create({ studentId, badgeId: badge.id, courseId }); await this.awardXp(studentId, courseId, 'badge_earned'); await this.notifyBadgeEarned(studentId, badge); } } } } 

Чому подієво-орієнтована архітектура?

Це дозволяє: обробляти 10 000+ подій на хвилину, легко додавати нові типи дій, гарантувати атомарність нарахування XP та бейджів.

Повний стек технологій Laravel 11, PostgreSQL 15, Redis 7, React 18, TypeScript 5. Docker, Nginx, черга Horizon, кеш leaderboard з TTL 60 секунд.

Порівняння підходів

Підхід Продуктивність Гнучкість Складність впровадження
Пакетна обробка (CRON) Низька, затримка до 1 години Середня Низька
Подієво-орієнтований Висока, реальний час Висока Середня
Тригери БД Середня, але блокує таблиці Низька Висока

Наш подієво-орієнтований підхід у 3 рази швидший за пакетну обробку та в 2 рази гнучкіший за тригери. Економія на обчислювальних ресурсах порівняно з тригерами — до $4 000 на рік при навантаженні 50 000 подій на день.

Як реалізувати систему streak?

Streak — серія днів з активністю поспіль. Алгоритм:

  • При кожному вході перевіряємо дату останньої активності.
  • Якщо вчора — збільшуємо streak на 1.
  • Якщо сьогодні — нічого не міняємо.
  • Якщо пропуск — скидаємо streak.
async function updateStreak(studentId, courseId) { const today = new Date().toISOString().split('T')[0]; const record = await db.studentXp.findOne({ studentId, courseId }); if (record.lastActivity === today) return; const yesterday = new Date(Date.now() - 864e5).toISOString().split('T')[0]; if (record.lastActivity === yesterday) { await db.studentXp.increment({ studentId, courseId }, 'streakDays', 1); } else { await db.studentXp.update({ studentId, courseId }, { streakDays: 1 }); } await db.studentXp.update({ studentId, courseId }, { lastActivity: today }); } 

Streak tiers: 3 дні → +50 XP, 7 днів → +200 XP, 30 днів → +1000 XP.

Таблиця нарахування XP

Дія XP Коментар
lesson_completed 50
assignment_submitted 30
assignment_graded_pass 100 >=70%
assignment_graded_excellent 150 >=90%
forum_post_created 10
forum_post_upvoted 5
streak_7_days 200
streak_30_days 1000
course_completed 500

Процес роботи та терміни

  1. Аналітика — вивчаємо вашу LMS, виявляємо точки мотивації (1-2 дні)
  2. Проектування — визначаємо систему балів, бейджів та рівнів (2 дні)
  3. Реалізація — пишемо код з використанням Laravel 11 + PostgreSQL (5-7 днів)
  4. Тестування — навантажувальне тестування leaderboard з імітацією 1000 студентів (1-2 дні)
  5. Деплой — розгортаємо на вашому сервері, навчаємо адміністраторів (1 день)

Базова система (XP + рівні + 10-15 бейджів + leaderboard) — від 7 до 10 днів. З кастомними UI-компонентами — до 14 днів.

Що входить в роботу

  • Документація API для інтеграції з вашою LMS
  • Налаштування Redis-кешу та черг
  • Адаптивний UI-компонент (React/Next.js)
  • Навчання адміністратора: як додавати бейджі, змінювати умови
  • Підтримка 2 тижні після запуску

Зв'яжіться з нами — отримайте консультацію та оцінку вашого проекту за 2 дні. Замовте розробку gamification-модуля під ключ.

Модель даних та leaderboard

CREATE TABLE xp_events ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), student_id UUID REFERENCES users(id), course_id UUID REFERENCES courses(id), event_type VARCHAR(100) NOT NULL, entity_id UUID, xp_awarded INT NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE badge_definitions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), slug VARCHAR(100) UNIQUE NOT NULL, name VARCHAR(200), description TEXT, icon_url VARCHAR(2000), condition_type VARCHAR(100), condition_value JSONB, xp_reward INT DEFAULT 0 ); CREATE TABLE student_badges ( student_id UUID REFERENCES users(id), badge_id UUID REFERENCES badge_definitions(id), awarded_at TIMESTAMPTZ DEFAULT NOW(), course_id UUID REFERENCES courses(id), PRIMARY KEY(student_id, badge_id) ); CREATE TABLE student_xp ( student_id UUID REFERENCES users(id), course_id UUID REFERENCES courses(id), total_xp INT DEFAULT 0, level INT DEFAULT 1, streak_days INT DEFAULT 0, last_activity DATE, PRIMARY KEY(student_id, course_id) ); 
async function getLeaderboard(courseId: string, limit = 20): Promise<LeaderboardEntry[]> { const cacheKey = `leaderboard:${courseId}`; const cached = await redis.get(cacheKey); if (cached) return JSON.parse(cached); const data = await db.studentXp.findAll({ where: { courseId }, order: [['totalXp', 'DESC']], limit, include: [{ model: db.users, attributes: ['name', 'avatar'] }], }); const result = data.map((row, idx) => ({ rank: idx + 1, studentId: row.studentId, name: row.user.name, avatar: row.user.avatar, xp: row.totalXp, level: row.level, streakDays: row.streakDays, })); await redis.setex(cacheKey, 60, JSON.stringify(result)); return result; } 

UI компоненти

XP bar — прогрес до наступного рівня з анімацією заповнення. При отриманні нових XP — спливаючий +50 XP тост. Badge showcase — сітка бейджів у профілі. Отримані — кольорові, ще не отримані — сірі з іконкою замка та підказкою про умову. Streak counter — вогник-іконка з кількістю днів. При щоденному заході — анімоване підтвердження продовження streak.