Реализация системы челленджей для вовлечения в мобильном приложении
Челленджи отличаются от достижений тем, что они временны, часто социальны, и требуют активного участия. «Пробеги 50 км за август» — это не «разблокировал бейдж», это обязательство с дедлайном. Именно срочность и коллективность создают вовлечение.
Типология челленджей
Solo challenges — пользователь vs цель. Фиксированный период, целевое значение. run_50km_august, meditate_20_days. Наиболее простые в реализации.
Community challenges — все пользователи участвуют вместе в достижении коллективной цели. «Вместе пробежим 100 000 км в марте». Прогресс — агрегат всех участников. Мотивирует через принадлежность к группе.
Head-to-head — два пользователя или команды соревнуются напрямую. Добавляет real-time аспект и нотификации о прогрессе соперника.
Weekly/monthly recurring challenges — повторяются по расписанию. Системно создаёт новый повод вернуться в приложение каждую неделю.
Модель данных
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. Важно — один обработчик события, не дублировать логику по разным системам.
Временные ограничения и Edge Cases
Дедлайн челленджа — самый частый источник жалоб пользователей. Типичные проблемы:
«Я выполнил задание, но челлендж не засчитался» — событие пришло на сервер в 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 недели. Стоимость рассчитывается индивидуально.







