Как построить фан‑сайт для шоу Битва экстрасенсов

Голосуй за фаворитов Битвы экстрасенсов в реальном времени, отслеживай статусы участников и создавай личный рейтинг сильнейших магов сезона!

Дата публикации:


Шоу «Битва экстрасенсов» уже много лет привлекает внимание зрителей благодаря мистическим испытаниям, жарким спорам в жюри и динамичному голосованию. Современный фан‑сайт должен не только предоставлять новости и расписание эпизодов, но и позволять пользователям:

  • Следить за текущим статусом каждого участника (в игре, Eliminated, Winner).
  • Оценивать выступления и формировать рейтинг экстрасенсов.
  • Участвовать в онлайн‑голосовании, влияющем на дальнейшее продвижение в шоу.

В этой статье мы подробно разберём, как построить такой сайт с нуля: от выбора технологий до реализации функционала статуса и рейтинга.


Планирование проекта

Определение целевой аудитории

Основные пользователи:

  1. Фанаты шоу (возраст 18‑45 лет).
  2. Журналисты и блогеры, следящие за новостями.
  3. Рекламодатели и спонсоры, заинтересованные в баннерах и партнёрских материалах.

Список обязательных функций

  • Главная страница с анонсом текущего сезона.
  • Страница участников с карточками (фото, имя, статус, рейтинг).
  • Система голосования (50/50: оценки жюри + голос зрителей).
  • Раздел новостей и анонсов.
  • Архив эпизодов (видео, даты, краткое содержание).
  • Админ‑панель для управления участниками, статусами, рейтингами и контентом.
  • Адаптивный дизайн (мобильные устройства, планшеты, десктоп).

Выбор технического стека

Фронтенд

Для быстрой разработки и удобной поддержки рекомендуется использовать:

  • JavaScript (ES6+) для интерактивности.
  • Библиотека React (или Vue.js) – упрощает работу с состоянием участников и рейтингами.
  • UI‑фреймворк: Bootstrap 5 или Tailwind CSS – ускоряет стилизацию и обеспечивает адаптивность.

Бэкенд

Варианты:

  • Node.js + Express – лёгкий, высокопроизводительный, хорош для реального времени (WebSocket).
  • Python + Django – мощная ORM, готовая админ‑панель, удобно для сложных запросов к БД.
  • PHP + Laravel – если команда уже работает с этим стеком.

Для демонстрации далее будем рассматривать стек Node.js/Express + PostgreSQL.

База данных

Оптимальный выбор – реляционная БД:

  • PostgreSQL – поддерживает JSONB, удобно для хранения гибких данных (например, метаданных голосований).
  • Таблицы: participants, seasons, episodes, ratings, votes, statuses.

Дополнительные сервисы

  • WebSocket (Socket.io) – для мгновенного обновления рейтинга во время голосования.
  • CDN (Cloudflare) – ускорение доставки статических файлов.
  • Хранилище изображений – AWS S3 или аналогичное для фото участников и скриншотов эпизодов.
  • SSL‑сертификат – обязателен для защиты данных пользователей.

Архитектура приложения

Схема взаимодействия:

+----------------+ +----------------+ +-------------------+
| Клиент (SPA) | <---> | API Gateway | <---> | Бэкенд (Node) |
+----------------+ +----------------+ +-------------------+
 | |
 v v
 +----------------+ +-----------------+
 | WebSocket Server| | PostgreSQL DB |
 +----------------+ +-----------------+

API‑эндпоинты (REST)

  • GET /api/participants – список всех участников с полями: id, name, photo, status_id, rating.
  • GET /api/participants/:id – детальная информация об участнике.
  • POST /api/votes – сохранение голоса зрителя (participant_id, value, user_ip).
  • GET /api/ratings – текущий рейтинг (сумма баллов жюри + средний голос зрителей).
  • PUT /api/participants/:id/status – изменение статуса (админ).

WebSocket события

  • vote_update – передаёт новый суммарный голос участника всем подключённым клиентам.
  • status_change – оповещает о смене статуса (например, выбыл).

Проектирование базы данных

Таблица participants

CREATE TABLE participants (
 id SERIAL PRIMARY KEY,
 name VARCHAR(100) NOT NULL,
 photo_url TEXT,
 season_id INTEGER REFERENCES seasons(id),
 status_id INTEGER REFERENCES statuses(id),
 rating NUMERIC(5,2) DEFAULT 0.00
);

Таблица statuses

CREATE TABLE statuses (
 id SERIAL PRIMARY KEY,
 label VARCHAR(30) UNIQUE NOT NULL -- например: 'InGame', 'Eliminated', 'Winner'
);

Таблица votes

CREATE TABLE votes (
 id SERIAL PRIMARY KEY,
 participant_id INTEGER REFERENCES participants(id),
 user_ip INET NOT NULL,
 value SMALLINT CHECK (value BETWEEN 1 AND 10),
 voted_at TIMESTAMP DEFAULT NOW
);

Вычисление рейтинга

Рейтинг формируется как:

rating = (jury_score * 0.5) + (average_user_vote * 0.5)

Где jury_score – средняя оценка жюри за последний эпизод (можно хранить в отдельной таблице episode_scores).


Реализация фронтенда

Структура страницы участников

<section class="participants-list">
 <h2>Участники текущего сезона</h2>
 <div class="grid">
 <!-- пример карточки участника -->
 <div class="card">
 <img src="{{participant.photo_url}}" alt="{{participant.name}}">
 <h3>{{participant.name}}</h3>
 <p class="status">{{participant.status.label}}</p>
 <p class="rating">Рейтинг: <span>{{participant.rating}}</span></p>
 <button class="vote-btn" data-id="{{participant.id}}">Проголосовать</button>
 </div>
 </div>
</section>

Голосование через AJAX

document.querySelectorAll('.vote-btn').forEach(btn => {
 btn.addEventListener('click', async e => {
 const participantId = e.target.dataset.id;
 const value = prompt('Оцените участника от 1 до 10:', '5');
 if (value === null) return;
 const num = parseInt(value, 10);
 if (isNaN(num) || num < 1 || num > 10) {
 alert('Введите число от 1 до 10');
 return;
 }
 await fetch('/api/votes', {
 method: 'POST',
 headers: {'Content-Type': 'application/json'},
 body: JSON.stringify({participant_id: participantId, value: num})
 });
 // Оптимистичное обновление UI
 e.target.textContent = 'Голос учтён';
 e.target.disabled = true;
 });
});

Обновление рейтинга в реальном времени

const socket = io; // подключаемся к WebSocket серверу
socket.on('vote_update', data => {
 const card = document.querySelector(`.card[data-id="${data.participant_id}"]`);
 if (card) {
 const ratingEl = card.querySelector('.rating span');
 ratingEl.textContent = data.new_rating.toFixed(2);
 }
});

Админ‑панель

Для управления участниками, статусами и контентом удобно использовать готовую админку:

  • Если выбран Django – подключить django.contrib.admin.
  • Если Node/Express – можно развернуть AdminBro или ForestAdmin.

Основные возможности:

  • Добавление/редактирование участников (фото, биография).
  • Изменение статуса после каждого эпизода.
  • Ввод оценок жюри (сохраняются в episode_scores);
  • Модерация голосов (удаление подозрительных IP‑адресов).
  • Публикация новостей и анонсов.

Тестирование и отладка

Юнит‑тесты

Для бэкенда рекомендуется использовать:

  • Jest (Node) или PyTest (Python).
  • Покрытие функций расчёта рейтинга, обработки голосов, изменения статуса.

Интеграционное тестирование

Симулируем сценарий:

  1. Участник получает оценку жюри 8.0.
  2. Зрители голосуют: средняя оценка 6.5.
  3. Ожидаемый рейтинг = (8.00.5 + 6.50.5) = 7.25.
  4. Проверяем, что API возвращает именно это значение.
  5. Нагрузочное тестирование

    Используем k6 или Artillery для имитации 1000 одновременных голосований, чтобы убедиться, что WebSocket и БД выдерживают нагрузку.


    Развёртывание и эксплуатация

    Контейнеризация

    Создаём Dockerfile для бэкенда и фронтенда, затем объединяем их в docker-compose.yml:

    version: '3.8'
    services:
     backend:
     build: ./backend
     ports: ["3000:3000"]
     environment:
     ‒ DATABASE_URL=postgres://user:pass@db:5432/bitextrasens
     depends_on:
     ‒ db
     frontend:
     build: ./frontend
     ports: ["80:80"]
     db:
     image: postgres:15
     environment:
     ‒ POSTGRES_USER=user
     ‒ POSTGRES_PASSWORD=pass
     ‒ POSTGRES_DB=bitextrasens
     volumes:
     ‒ pgdata:/var/lib/postgresql/data
    volumes:
     pgdata:
    

    CI/CD

    Настраиваем pipeline в GitHub Actions или GitLab CI:

    • Запуск тестов при каждом push.
    • Сборка Docker‑образов.
    • Деплой в Kubernetes или на VPS с помощью Traefik (обратный прокси + SSL).

    Мониторинг

    • Логи: ELK stack (Elasticsearch, Logstash, Kibana) или Loki + Promtail.
    • Метрики: Prometheus + Grafana (время ответа API, количество активных WebSocket‑соединений).
    • Оповещения: интеграция с Alertmanager для сигналов о высокой ошибке 5xx или падении БД.

    Создание сайта «Битва экстрасенсов» со статусом и рейтингом – это комплексный проект, требующий продуманной архитектуры, современного стека технологий и внимания к деталям UX/UI. Следуя предложенному плану:

    1. Определить функционал и аудиторию.
    2. Выбрать подходящие технологии (React + Node/Express + PostgreSQL).
    3. Спроектировать БД и API, предусмотрев WebSocket для мгновенных обновлений.
    4. Реализовать адаптивный фронтенд с интерактивным голосованием.
    5. Построить удобную админ‑панель для управления участниками и статусами.
    6. Провести тестирование, настроить CI/CD и мониторинг.

    В результате вы получите надёжный, масштабируемый портал, который будет не только информировать фанатов о шоу, но и активно вовлекать их в процесс голосования, влияя на рейтинг и судьбу участников. Удачной разработки!


    Автор статьи: ваш помощник по созданию веб‑проектов.