Методология
Как мы строим каждую статистику
BrawlVision сочетает официальное API Supercell, нашу собственную систему семплинга PRO-игроков и несколько шагов статистического сглаживания, чтобы давать вам стабильные, сопоставимые числа, честные по поводу собственной неопределённости. Эта страница описывает каждый из шагов с точными формулами и частотами обновления.
Последнее обновление: 2026-04-30
Источники данных
Всё, что мы показываем, происходит из трёх источников, которые мы держим аудируемыми: публичный API Supercell (developer.brawlstars.com), CDN Brawlify (cdn.brawlify.com) и наша собственная база Supabase, в которой персистируются бои и агрегаты, не раскрываемые официальным API дальше последних 25 матчей на игрока.
API Supercell — каноничный источник структурных данных: бойцов, гаджетов, звёздных сил, гиперзарядов, снаряжения и ротации событий. Однако оно не возвращает картинки бойцов, редкость и длинные описания. Эти поля мы сверяем с CDN Brawlify, который работает независимо и иногда отстаёт от Supercell на один-три дня. Когда в API появляется новый боец, которого ещё нет в Brawlify, мы держим локальную карту редкости (BRAWLER_RARITY_MAP), чтобы страница бойца корректно отрисовывалась в день релиза.
Наша база хранит два класса записей в meta_stats: source=user (реальные бои премиум-пользователей с включённой синхронизацией) и source=global (автоматический сэмплинг из топ-рейтингов PRO). Любая публичная статистика на сайте считается с фильтром source=global, чтобы личные данные никогда не утекали на публичные страницы.
Как мы строим PRO-данные
Слой "PRO" в BrawlVision — это агрегаты, посчитанные на свежих боях лучших игроков мира. Каждые шесть часов cron-задача (meta-poll) опрашивает официальные рейтинги Supercell по одиннадцати странам — там, где сосредоточена соревновательная активность — и строит дедуплицированный пул примерно из 2 100 уникальных игроков из топ-200 каждой страны.
Над этим пулом применяется вероятностный сэмплер, чтобы популярные комбинации (карта, режим) не доминировали в датасете и не маскировали редкие. Вероятность принять отдельный бой — p = min(1, (minLive + 1) / (current + 1)), где minLive — счётчик наименее представленной комбинации, а current — счётчик комбинации кандидата. Недосэмплированные комбинации получают больший вес, насыщенные перестают расти.
Cron итерирует до META_POLL_MAX_DEPTH = 1 000 игроков за запуск с мягким бюджетом 270 секунд, чтобы оставаться в пределах maxDuration 300 с serverless-функции. Каждый ответ содержит блок "adaptive" с диагностикой: число итераций, опрошенных игроков, счётчики по режимам — чтобы аномалии сэмплера были видны в продакшене.
Bayesian Win Rate
Наивный винрейт (победы, делённые на матчи) вводит в заблуждение, когда матчей мало. Боец с 3 победами и 0 поражений на новой карте показывает 100 %, которые ничего не значат. BrawlVision применяет байесовское сглаживание, чтобы исправить это искажение и вернуть число, сравнимое между бойцами с очень разными выборками.
Формула имеет вид WR_bayesian = (победы + α·μ) / (битвы + α). Параметр α взвешивает, сколько воображаемых матчей мы добавляем, а μ задаёт результат, который мы им присваиваем. Мы используем α = 30, что равносильно добавлению 30 предыдущих битв до того, как посмотреть на реальные данные.
До сентября 2026 года эти воображаемые матчи стоили 50 %, и это была неверная величина. Наша таблица хранит одну строку на битву, строку опрошенного игрока, который входит в топ-200 своей страны и выигрывает 71,4 % своих матчей (61 400 побед на 85 970 битв в окне 14 дней, измерено 7 сентября 2026 года). Сжатие к 50 % данных, центрированных на 71,4 %, тянуло вниз любую ячейку с малым числом матчей, и чем меньше была выборка, тем сильнее тянуло. Сегодня μ равно 0,714, и это измеренная нами база.
Вес априорного распределения падает по мере роста выборки. При 1000 битв и 530 победах результат выходит на (530 + 21,42) / 1030 = 53,5 %, совсем близко к сырым 53,0 %. При 3 битвах и 3 победах он выходит на 74,0 % вместо наивных 100 %. Сглаживание весит только тогда, когда выборка действительно мала.
Скорректированная сила
Винрейт, который мы публикуем, смешивает две вещи. Одна состоит в том, насколько хорош боец, вторая в том, против кого ему пришлось играть. Боец, который чаще всего попадает в удобные противостояния, выходит наверх, и о его наборе способностей это говорит немного. Скорректированная сила разделяет эти две вещи и оценивает, как часто такой боец побеждал бы против соперника среднего уровня.
Расчёт представляет собой модель Bradley-Terry, подогнанную методом MM по таблице противостояний за последние 14 дней. Каждая пара бойцов симметризуется перед подгонкой, потому что наши строки всегда записываются со стороны опрошенного игрока, а эта сторона идёт с преимуществом. По парам, где есть минимум 30 дуэлей в каждую сторону, винрейт A против B вместе с винрейтом B против A дают медиану 138 %, тогда как симметричные данные давали бы 100 %. Если считать каждую дуэль по одному разу с каждой стороны, это преимущество входит в пользу обоих и взаимно гасится. Результат публикуется как ожидаемый винрейт против медианного бойца подгонки, поэтому в этой шкале 50 % означает ничью.
Цифра снимает состав соперников и среднее преимущество выборки. Она не снимает мастерство того, кто играет бойцом. Ни meta_stats, ни meta_matchups не хранят идентификатор игрока, поэтому вычесть уровень играющего с нашими данными невозможно; для этого пришлось бы записывать рейтинг опрошенного игрока в момент загрузки. Поэтому списки сайта по-прежнему сортируются по наблюдаемому винрейту, а сила стоит рядом. И поэтому же наблюдаемый винрейт держится около 72 %, а не около 50 %. Выборка состоит из матчей игроков топ-200 из одиннадцати стран, которые выигрывают около 72 % сыгранного, так что в этой шкале 72 % описывает обычного бойца. Силу мы публикуем только для бойцов с минимум 400 записанными дуэлями против 20 разных соперников; ниже этого порога цифра опускается вместо показа числа, которое не выдерживает проверки.
Comfort Score
Comfort Score — собственная метрика BrawlVision, отвечающая на вопрос "с каким бойцом ты на самом деле играешь лучше среднего?". Это не чистый Win Rate: он сочетает три компонента с весами 60/30/10, покрывая разные стороны личной формы.
Главный компонент (60 %) — WR игрока с этим бойцом, сглаженный байесовски как и глобальный мета, чтобы редко играемый боец не искажал ранг. Средний компонент (30 %) — разница между этим личным WR и общим мета-WR бойца: игрок с 55 % на SHELLY при глобальном мета 48 % набирает больше comfort, чем игрок с 55 % на бойце с мета 53 %, потому что относительный лифт выше.
Финальный компонент (10 %) — нормализованная частота использования: при прочих равных играть бойца 100 раз весит больше, чем 10, потому что постоянство вознаграждается. Точные формулы и веса живут в src/lib/analytics/compute.ts и применяются одинаково на каждом вызове эндпоинта, чтобы ранг был воспроизводим.
7-дневные тренды
У каждого публичного бойца есть индикатор тренда "+X,Y%" или "−X,Y%", показывающий, как изменился его мета-WR за последние 7 дней по сравнению с предыдущими 7 (всего окно 14 дней). Расчёт идёт на source=global с минимумом MIN_BATTLES_PER_TREND_WINDOW = 3 боя в каждой половине окна — если одна из половин ниже порога, мы возвращаем null, и UI скрывает стрелку, не выдумывая слабый сигнал.
Тренд предрасчитывается каждые шесть часов в маленькой таблице (public.brawler_trends, одна строка на бойца) задачей pg_cron. Делать это в БД, а не в ответе эндпоинта, позволяет не сканировать десятки тысяч строк 14-дневного среза при каждом ISR-обновлении. Если предрасчитанная таблица старше 12 часов или пуста, эндпоинт переходит на пагинированный inline-маршрут поверх meta_stats, возвращающий тот же ответ ценой большей задержки. Пагинация нужна, потому что PostgREST молча обрезает непагинированные запросы до 1 000 строк — что однажды заставило большинство бойцов отдавать null по ложной недосемплированности.
Логика дублирована by design: TypeScript-версия в src/lib/brawler-detail/trend.ts (маршрут детали) и SQL-версия в supabase/migrations/022_*.sql (массовый маршрут). Обе используют один и тот же порог, окно и фильтр source=global. Если они разойдутся, страница бойца и агрегатная страница покажут разные числа для одного и того же бойца, поэтому любое изменение применяется к обеим.
Частота обновления
Как часто данные обновляются — влияет на интерпретацию, поэтому мы документируем явно. Статичные страницы (включая эту) используют ISR (Incremental Static Regeneration) с ревалидацией раз в 24 часа. Страницы с динамическими данными кэшируют ответ API, пока соответствующая задача не инвалидирует его.
Бойцы, гаджеты и звёздные силы синхронизируются с API Supercell с серверным кэшем 24 часа. Meta-poll (PRO-данные) запускается каждые 6 часов и пишет свежие строки в meta_stats. Предрасчёт 7-дневных трендов запускается в pg_cron на "17 */6 * * *" (минута 17 каждых шести часов), чтобы не сталкиваться с meta-poll. Внутриигровая ротация событий обновляется каждые 30 минут.
Отдельные бои премиум-пользователей с включённой синхронизацией скачиваются сразу после каждой партии в скользящем окне через cron sync. Попадая в нашу базу, они подпитывают meta_stats с source=user и являются основой приватной аналитики в разделе профиля; они никогда не появляются в публичных агрегатах и никогда не смешиваются с source=global.
Часто задаваемые вопросы
Почему WR редко играющего бойца не 0 % или 100 %?+
Потому что мы применяем байесовское сглаживание с приором, центрированным на 50 %. При очень малом числе матчей показанное число близко к 50 %; с ростом выборки оно сходится к реальному WR. Это сделано намеренно: 100 % при 3 матчах — это шум, не информация.
Используют ли публичные страницы данные реальных пользователей?+
Нет. Каждый публичный агрегат фильтрует по source=global, который содержит только бои из автоматического сэмплинга PRO-рейтингов. Приватные бои премиум-пользователей хранятся с source=user и никогда не попадают на публичные страницы.
Что происходит, когда Supercell выпускает нового бойца?+
Список бойцов берётся из официального API, поэтому полный ростер появляется на сайте в день релиза. Редкость и картинки приходят из Brawlify, который может отставать на один-три дня; мы держим локальную карту редкости (BRAWLER_RARITY_MAP) как fallback на эти первые дни.
Почему некоторые тренды показывают прочерк вместо процента?+
Тренд показывается, только если в каждой половине 14-дневного окна есть хотя бы 3 боя в source=global. Когда боец редко встречается, мы предпочитаем ничего не показывать, чем число со слабым сигналом.
Использует ли сайт ИИ для генерации описаний?+
Описания генерируются динамически из наших данных (лучшая карта, лучший режим, байесовский WR на бойца). Мы не копируем тексты из Brawlify или вики и не используем языковые модели для раздувания контента.
Вопросы или поправки?
Если вы заметили методологическую ошибку или хотите предложить улучшение, напишите нам. Мы держим эту страницу синхронизированной с каждым релевантным изменением расчётов.
