Реалізація системи челленджів для вовлечення у мобільному додатку
Челленджи відрізняються від досягнень тим, що вони часові, часто соціальні, та вимагають активної участі. «Пробігти 50 км за серпень» — це не «розблокував бейдж», це обов'язок з дедлайном. Саме терміновість та колективність створюють вовлечення.
Типологія челленджів
Solo challenges — користувач vs ціль. Фіксований період, цільове значення. run_50km_august, meditate_20_days. Найпростіші в реалізації.
Community challenges — всі користувачі беруть участь разом в досягненні колективної цілі. «Разом пробігнемо 100 000 км в березні». Прогрес — агрегат всіх учасників. Мотивує через належність до групи.
Head-to-head — два користувачі або команди змагаються прямо. Додає real-time аспект та сповіщення про прогрес суперника.
Weekly/monthly recurring — повторюються за розкладом. Системно створює новий повід повернутися в додаток кожен тиждень.
Модель даних
challenge:
id, title, description
type: ENUM(solo, community, head_to_head, recurring)
metric: VARCHAR -- "workout_count", "distance_km", "streak_days"
target_value: DECIMAL
starts_at, ends_at: TIMESTAMP
xp_reward, badge_id: nullable
is_active: BOOL
user_challenge_participation:
user_id, challenge_id
current_value: DECIMAL -- поточний прогрес
joined_at: TIMESTAMP
completed_at: nullable TIMESTAMP
rank: nullable INT -- для соревновательних
Прогрес обновляется event-driven: та ж подія workout_completed, яка начисляє XP, перевіряє активні челленджи користувача та інкрементує current_value. Важливо — один обробник подій, не дубльована логіка по різних системах.
Часові обмеження та граничні випадки
Дедлайн челленджу — найбільш частий джерело скарг користувачів. Типові проблеми:
«Я виконав завдання, але челлендж не засчитався» — подія прийшла на сервер о 23:59:58, але обробилася о 00:00:01 наступного дня. Використовуй grace period 5 хвилин після ends_at.
«Я був у самольті без інтернету» — подія збережена локально з occurred_at = yesterday, відправлена сьогодні. Бекенд повинен приймати подій з occurred_at у минулому (з розумним обмеженням, наприклад 7 днів), а не за серверним часом отримання.
Двійне начисленння прогресу — при ретрансмісії подій від клієнта. Ідемпотентний ключ (event_id) у кожній подій, унікальний constraint на (user_id, event_id).
Соціальна частина
Push-сповіщення про прогрес у community challenge: «Наша група виконала 67% цілі, залишилось 3 дні» — посилаємо всім учасникам раз на день. Firebase Cloud Messaging з topic messaging: кожен challenge — окремий topic, підписка при join.
Лента активності учасників: «Анна пробігла 5 км» — додає соціальний pressure. Технічно: challenge_activity_feed(user_id, challenge_id, action, value, occurred_at). Клієнт тягне останні N записів при відкритті екрана челленджу.
Як виглядає на клієнті
Список активних та доступних челленджів з карточками: прогрессбар, дедлайн, кількість учасників. Екран челленджу: ціль, мій прогрес, лента активності, кнопка «Поділитися прогресом» (шеринг скриншота карточки через UIActivityViewController).
При завершенні — celebration overlay з анімацією, начисленння XP/бейджа, CTA «Присоєднатися до наступного челленджу».
Орієнтири за термінами
Solo challenges з прогресом та сповіщеннями — 3–5 днів (клієнт + бекенд). Community та head-to-head з лентою активності, real-time обновленнями та соціальними сповіщеннями — 2–3 тижні. Вартість розраховується індивідуально.







