КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ World of Tanks

Есть ещё какая-то неведомая система Ree, находящаяся в открытом доступе, но информации о ней — кот наплакал. Как я понял, она не используется в видеоиграх напрямую, но позволяет вести учёт рейтинга чего-либо непосредственно на сайте.

Засим откланяюсь. Всем хороших игр и высокого рейтинга.

Простыми словами о системах Elo, Glicko, Glicko-2 и TrueSkill.

Недавно мне стало интересно, как определяется мой ранг в среднестатистической онлайн-игре, поэтому я полез в Google и тут же нашёл ответ на свой вопрос.

Понятнее не стало. Поэтому я стал копать глубже, чтобы разобраться хотя бы поверхностно, как «для чайников», не вникая во все эти многоэтажные формулы. И нашел четыре рейтинговые системы, на которые опираются большинство современных онлайн-игр. Именно это системы и определяют, насколько хорошо (плохо) вы играете в игру.

Введение

Привет, хабравчане. С детства мне нравились цифры и возможность измерить всё и вся. Когда в средней школе я увлекся шахматами, побочным эффектом оказалось знакомство с системой рейтинга Эло. Мне (как и многим другим людям в мире) она показалась удобной и логичной, и с тех пор ко мне периодически возвращалась идея применения этой системы к разнообразным спортивным соревнованиям. Первой попыткой было её применение к многострадальному чемпионату России по футболу, и было мне тогда лет 13. Поскольку на тот момент я не только не владел навыками программирования, но даже элементарно не имел компьютера, все расчеты велись в тетрадке, что делало поддержание информации в актуальном состоянии довольно трудоемкой задачей. Спустя годы я вернулся к этой идее, выбрав своей мишенью НХЛ.

Разработан компанией Microsoft для игр сервиса Xbox Live. О работе этой системы в интернете есть даже отдельная презентация, разобраться в которой весьма затруднительно.

В отличие от Glicko-2, имеет всего два параметра. Больше никаких там рейтингов изменчивости, только «мю» и «сигма». Первый определяет скилл игрока, второй — степень неопределённости в этом скилле (что-то похожее на RD).

Мю— вертикальная линия на отметке 25 (это не основной рейтинг, а отметка, указывающая положение диапазона на кривой); сигма — горизонтальная, описывающая конкретный диапазон. Зелёная область — рейтинг игрока (сама кривая) при значении мю в пределах от 15 до 20

Игроки с такой системой начинают на отметке 25 (это мю) при сигме в 25/3. Это означает, что истинный рейтинг новичков колеблется примерно в районе 21-29 очков. Чем больше матчей сыграл игрок, тем меньше диапазон сигма и тем точнее система определяет рейтинг. Крутость игрока определяется его средней эффективностью в нескольких последних матчах.

Почему НХЛ?

Надо заметить, что идея использовать систему Эло за пределами шахматного мира далеко не нова. Система используется для создания рейтингов также в шашках и го, а в 2018 году система на основе рейтинга Эло взята на вооружение и ФИФА (международной федерацией футбола). Также существует альтернативный рейтинг Эло футбольных сборных.

Так уж получилось, что в последние годы я являюсь большим поклонником НХЛ. Н ХЛ (Национальная хоккейная лига) — это лига по хоккею с шайбой, объединяющая сильнейшие клубы США и Канады. Благодаря большим финансовым возможностям и престижу данная лига привлекает лучших игроков со всего мира, в том числе и из России. Именно потому, что НХЛ мне интересна и я активно за ней слежу, выбор пал на нее. Никаких объективных причин не было.

Проведя быстрый поиск в интернете, я обнаружил несколько сайтов, реализующих идею ранжирования команд НХЛ с применением рейтинга Эло. Но некоторые из них были заброшены лет пять назад, а некоторые давали просто текущие рейтинги команд. Я же хотел иметь возможность просмотра рейтингов команд на любой день в истории лиги.

Elo выглядит вполне себе справедливо, да вот не совсем. Допустим, в матче встретились два игрока с рейтингом 1600. Оба должны играть одинаково хорошо, вот только первый играет раз в неделю (или по каким-то причинам вообще не заходил в игру с месяц), а второй играл днями и ночами. Скорее всего, второй игрок победит.

Система Glicko учитывает этот фактор и вводит новый параметр – рейтинговое отклонение, сокращенно – RD (потому что Ratings Deviation). Чем реже игрок заходит в игру, тем выше его RD. Суть системы Glicko заключается в том, что у игрока с высоким RD невозможно точно определить его рейтинг. Система не может определить, насколько хорош игрок, если он редко играет, поэтому задает рейтинги в виде интервалов.

Поскольку игрок в системе Glicko имеет и рейтинг, и RD, то обычно более информативно описать силу игрока в виде интервала (нежели просто указать его значение). Одним из путей является создание 95% доверительного интервала.

Наименьшим значением интервала является рейтинг игрока минус двойной RD, а наивысшим значением является рейтинг игрока плюс двойной RD. Так, например, если чей-либо рейтинг равен 1850 и RD равно 50, то интервал будет простираться между 1750 и 1950. Мы можем сказать тогда, что мы на 95% уверены, что реальная сила игрока лежит между 1750 и 1950. Если у игрока низкий RD, то интервал будет уже, и мы будем на 95% уверены в реальной силе игрока в меньшем интервале значений.

Марк Е. Гликман, профессор Бостонского университета

Зависимость упомянутого RD от времени. Скачки — сыгранные матчи. R Dрастёт со временем и падает после очередной игры

Здесь могли находиться формулы расчета рейтинга, но их нет. Хотите их увидеть — они вверху поста. Считается рейтинг Glicko гораздо сложнее рейтинга Elo.

Так что же с той игрой, где у игрока А и В по 1600 очков? Если победит тот, кто играл днями напролёт, то он получит меньшее количество очков, чем если бы победил его оппонент. А после игры RD обоих оппонентов снизится.

Пример игры с Glicko — Planetary Annihilation

Что такое рейтинг Эло?

Рейтинг Эло — это система, разработанная в середине XX века американским ученым венгерского происхождения Арпадом Эло для применения в шахматах. Сначала она была взята на вооружение Шахматной федерацией США, а потом, в 1970 году, и ФИДЕ. Данная система применяется и в наши дни для оценки силы шахматистов.

В основе данной системы лежит простое предположение. Если рейтинг игрока А больше рейтинга игрока Б, то игрок А должен выигрывать у игрока Б. Чем больше разница рейтингов, тем больше вероятность победы. Если игрок А у игрока Б не выигрывает, значит рейтинги не отражают реального соотношения силы играющих, и должны быть скорректированы. Просто? Просто. Логично? Логично.

Если расписывать более подробно, то суть такая. Перед игрой, серией игр или турниром на основе рейтингов соревнующихся рассчитывается вероятность победы каждого из них. Формула расчета не отличается простотой, но и ничего особенно сложного в ней нет:

где Ra и Rb — это рейтинги игроков А и Б соответственно, а Pa — вероятность победы игрока А. Таким образом, разница в рейтингах в 400 пунктов дает 90% вероятность победы игрока с более высоким рейтингом. Соответственно, вероятность победы второго игрока будет 1 — Pa. Далее вероятность победы вычитается из реального результата игрока в конкретной игре (1 — победа, 0 — поражение, 0,5 — ничья), эта разность умножается на коэффициент K, и таким образом получается количество пунктов, на которое должен измениться рейтинг игрока.

Например, у если у игрока А рейтинг 1100, а у игрока Б — 1050, то вероятность победы первого игрока будет 0,57, а игрока Б соответственно 0,43. И если игрок А победит, то его рейтинг увеличится на (1 — 0,57)K, а рейтинг игрока Б увеличится на (0 — 0,43)K, то есть уменьшится, т. к. коэффициент положительный. Коэффициент K по сути выбирается произвольно, от его величины зависит, насколько каждый конкретный результат влияет на рейтинг игрока. Изначально в системе Эло этот коэффициент был принят за 10, так что в нашем примере игрок А приобрел бы 4,3 очка рейтинга, а игрок Б потерял бы такое же количество (изменения рейтингов игроков в этой системе всегда симметричны).

Каждый новый игрок в системе Elo получает некое стартовое количество очков, например — 1500. Само количество непринципиально, главное – чтобы счётчик не ушёл в минус. При победе этот счётчик увеличивается, а при поражении — уменьшается, но количество очков, на которое изменяется рейтинг, непостоянное.

Хоть описание статьи и содержит в себе сочетание «простыми словами», я всё-таки должен вставить пару формул. Маленьких и простых, честно!

ЕА здесь — это то количество очков, которое игрок А получит после победы над игроком В; RA и RB — это текущие рейтинги игроков А и В

Рейтинг устроен так, что игрок с высоким рейтингом получит много очков после победы над игроком с низким, тогда как последний после победы над сильным оппонентом получит мало очков. Звучит несправедливо, вот только эти очки не прибавляются к рейтингу Elo, а проходят через ещё один круг подсчётов.

R’A — это новый рейтинг игрока А. К – это максимальное количество очков, которое игрок может получить или потерять за игру (обычно это 16). S A меняется в зависимости от результата игры: 1 при победе, 0 при поражении, 0,5 при ничье

Без паники! На примере всё сразу прояснится. В этом мне поможет игра с открытой (пользователи видят, как изменяется их ранг) Elo-системой — Brawlhalla.

Пример игры с Elo — Brawlhalla

Лично я люблю эту игру, но уж очень мне не нравится тамошняя система подбора игроков в рейтинговой игре. Новичка с рейтингом 1300 может спокойно кинуть к платине с рейтингом в 1800, и тогда на экране будет твориться такое, что можно будет заливать на pornhub в раздел «изнасилований». Платина, разумеется, победит. Какой будет её рейтинг после победы?

Про WoT:  Личный кабинет

1800+16*(1-(1 / (1 + 10^((1300-1800)/400)))) = 1800.85. Как изменится рейтинг новичка? 1300+16*(0-(1 / (1 + 10^((1800-1300)/400)))) = 1299.15. Короче говоря, рейтинги почти не поменяются. Что есть правильно: новичка кинуло к профессионалу, и он, очевидно, проиграл. Но что, если новичок выиграет? Изменим значения в формулах и посчитаем заново, как изменятся рейтинг.

Для платины: 1800+16*(0-(1 / (1 + 10^((1300-1800)/400)))) = 1784.85. Для новичка: 1300+16*(1-(1 / (1 + 10^((1800-1300)/400)))) = 1315.15. Рейтинг игроков изменился на 15,15 (а 16 — максимум) очков! Платина ушла в почти максимальный минус, а новичок — в плюс. Справедливо? Справедливо.

Это – ваш рейтинг. Скачки — сыгранные матчи. Вы получаете и теряете очки, но каждый раз — разное их количество

Вводим ещё один параметр! Теперь помимо основного рейтинга и RD появляется рейтинг изменчивости. Здесь система учитывает вероятность вашей победы или проигрыша.

Если вы играете стабильно, побеждая там, где должны победить и проигрывая более сильным соперникам, рейтинг изменчивости падает. Но если вы, имея платину, проигрываете бронзе или разрываете лучших игроков с подрубленными читами — рейтинг изменчивости будет расти.

Пример игры с модернизированной Glicko-2 — Counter-Strike: Global Offensive

Для меня Global Offensive — это пример игры, где вообще максимально непонятно, как меняется твой ранг. Ты можешь безрезультатно побеждать бесконечное количество игр, но после одного поражения тебя понизят. Valve не разглашает, как именно работает их рейтинговая система, и такой политики придерживаются и многие другие разработчики.

Можно было бы начать рассуждения со слов «с одной стороны, это плохо, потому что игроки не знают, сколько им играть до следующего ранга», но нет. Это – хорошо. Потому что будь их система на виду, как в упомянутой Brawlhalla, игроки смогли бы определить, за что даётся больше очков рейтинга, а за что – меньше. Игроки бы поняли, что за обезвреживание бомбы, например, даётся больше очков, чем за убийства в голову, а за высокую точность – больше, чем за спасение заложников.

С этой информацией армия игроков стала бы фармить, и уже через пару дней игру заполонили бы псевдо-элиты. А пока игроки просто знают, что для повышения нужно побеждать, и это – вся информация, которая и необходима для нормальной игры, не переходящей в задротство. Если интересно, то на DTF уже есть подробная статья про рейтинг в CS (есть даже график, похожий на тот, что я использовал выше, но как-то я не осилил тамошнее объяснение). Однако что-то я отвлекся от темы, скажем — это было небольшое отступление на конкретном примере.

Резюмируя, можно определить, из каких параметров состоит рейтинг Glicko-2. Во-первых, это основной рейтинг, показывающий, насколько хорош игрок. Во-вторых, это RD — показатель, определяющий, насколько точен основной рейтинг. В-третьих, это рейтинг изменчивости, определяющий стабильность игры у игрока. В-четвертых, это период времени, на котором производится расчёт. Ну и, если хотите посмотреть, как считается Glicko-2 — вот так. А может и не так, у меня просто интеллекта не хватило понять описанное (RD вроде есть, рейтинг изменчивости — тоже, а вообще, отстаньте от меня, я гуманитарий).

Время на прочтение

Рейтинг игроков (leaderboard, scores) для мобильной игры — вещь интересная и порой даже необходимая. В этой статье я расскажу о том, как добавить рейтинг игроков в приложение, созданное в Unity, т.к. в рунете информации об этом не так много. Кроме того, рейтинг будет кросплатформенный (android + iOS), однако без поддержки Windows Phone.


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Раздел 1. К ОНСОЛЬ РАЗРАБОТЧИКА

1. Считаем, что приложение уже опубликовано на Google Play, т.е. у нас есть package name, например com. AnonymousInteractives. NakedSnake


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

3. Жмем «Добавить новую игру» и указываем название игры и категорию. Тут может возникнуть некоторая путаница. Термин «игра» здесь означает игровой сервис. Название может не совпадать с реальным названием вашего приложения. У игрового сервиса появляется уникальный идентификатор, например 88171208539


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Раздел 2. Unity

1. Переходим на страницу проекта play-games-plugin-for-unity и скачиваем проект (ссылка «Download ZIP»). В архиве находим файл GooglePlayGamesPlugin-0.9.02.unitypackage

2. Открываем проект приложения в Unity

3. Дважды кликаем по GooglePlayGamesPlugin-0.9.02.unitypackage и импортируем пакет в проект


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

4. Переходим в меню File / Play Games — Android setup и вводим идентификатор нашего сервиса (см. шаг 3 из предыдущего раздела). Все, на этом настройка завершена!


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

5. Теперь осталось добавить пару строчек кода и у нас появится рейтинг игроков. Графический интерфейс рейтинга находится в Android SDK, так что нам не придется тратить на него время. В тоже время, никакой кастомизации UI не предусмотрено (кроме настроек в консоли разработчика — иконка рейтинга и единица измерения). На странице плагина (см. пункт 1) находится достаточно справочной информации, поэтому я без комментарием приведу код внесения записи в рейтинг игроков с последующим его отображением. Замечу, что процесс асинхронный, и на каждое действие приходит callback. Из-за этого могут возникнуть затруднения при внесении записей сразу в несколько рейтингов. Как вариант — реализация цепочек из callback. Альтернативно можно вызывать ReportScore параллельно и обрабатывать все callback таким образом, чтобы только последний из них открывал рейтинг вызовом ShowAchievementsUI

Раздел 3. Заключение

К сожалению, пока нет поддержки Windows Phone. Там все совсем печально, вас ждет низкоуровневая реализация взаимодействия с Azure и написание своего UI, готовое и рабочее решение найти не удалось.
На этом пока все, спасибо за внимание. В дальнейшем, если кому-то будет интересно, могу рассмотреть процесс создания web-приложения для модерации рейтингов (удаления читеров, например), т.к. в консоли разработчика нет для этого никаких средств.

Механики геймификации

Рейтинг. Что это и как его использовать в геймификации? Вопрос кажется простым, даже риторическим, но на деле и у такой очевидной механики есть много нюансов, в том числе, обусловленных эволюцией человека.


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Эта статья — первая из моего цикла статей о компонентах, механиках и интересных примерах геймификации. Поэтому некоторым общим терминам я буду давать краткие определения. Что такое “геймификация (игрофикация)”? Википедия дает определение: “применение для прикладного программного обеспечения и веб-сайтов подходов, характерных для компьютерных игр, в неигровых процессах с целью привлечения пользователей и потребителей, повышения их вовлеченности в решение прикладных задач, использование продуктов, услуг”.

Предпочитаю другой вариант: “геймификация — управление поведением пользователей системы с помощью игровых механик”. Разница между этими определениями в том, что системой может быть как веб-сайт или ПО, так и общественный парк или транспортная сеть. Геймификация применима не только в ИТ-сфере. Далее, некоторые игровые механики используются для повышения вовлеченности пользователей, некоторые — для привлечения пользователей, но это объединяется в обобщенное понятие “управление поведением”. Для внедрения геймификации важно знать, что пользователи в системе делают (могут делать, если система еще не используется), и что пользователи должны делать с точки зрения владельцев системы. Геймификация полезна для перехода от “делают” к “должны делать”.


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Рейтинг — простая и популярная игровая механика, используемая в геймификации. Точного определения термина “игровая механика” нет, порою под ним понимают что угодно — от баджей и ачивментов до поведенческих импульсов. Наведение порядка в используемой в геймификации терминологии — тема для отдельной статьи, здесь же ограничусь кратким объяснением, что я понимаю под игровой механикой. Это низший (наиболее конкретный) уровень проектирования геймифицированной системы, условные кубики конструктора Lego. Игровые механики выбираются и применяются тогда, когда верхние, более абстрактные уровни геймификации системы уже продуманы. Поэтому рейтинг, баджи, уровни — игровые механики, а вирусность или групповая работа — нет.

Рейтинг — числовой или порядковый показатель, отображающий важность или значимость определенного объекта или явления (определение из Википедии). Механика рейтинга связана с механикой очков и часто — с механикой уровней пользователя. Рейтинг без очков невозможен — система не поймет, в каком порядке отображать пользователей в рейтинге, рейтинг без уровней возможен.

Попробуем классифицировать рейтинги по значению для пользователей системы.

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

Еще один вариант классификации рейтингов: по тому, кто изменяет рейтинг пользователя — только система, только другие пользователи или система и пользователи. Вариант, когда только система изменяет рейтинг пользователя, наиболее распространен. Он часто используется в онлайн-играх. Игрок выполняет различные действия (убивает монстров, выполняет квесты), за это система начисляет очки опыта (рейтинга). Другие пользователи не влияют на рейтинг игрока в такой системе. Вариант, когда рейтинг пользователя изменяет не система, а другие пользователи системы, обычно используется вместе с доверительным рейтингом. Примеры: повышение или понижение кармы, положительные и отрицательные отзывы после сделок на торговых площадках. Возможен и комбинированный вариант, например в онлайн-вопросах. За ответ на вопрос пользователь автоматически получает баллы рейтинга от системы, а если другие пользователи признают ответ лучшим, то пользователь получает дополнительные баллы.

Следующий способ основан на положительном и отрицательном изменении рейтинга пользователя. Я выделяю условные “рейтинг плюс”, “рейтинг плюс-минус положительный”, “рейтинг плюс-минус отрицательный” и “рейтинг минус”. Первый вариант, “рейтинг плюс”, подразумевает только увеличение рейтинга пользователя. Такой вариант используется, например, для покупателей на аукционе eBay. По итогам сделки продавец оставляет покупателю только положительный отзыв или не оставляет его вовсе. Да, покупатель-мошенник может быть заблокирован администрацией, но его рейтинг снизиться не может (пока не станет сам плохо продавать).

Рейтинг плюс-минус положительный подразумевает как увеличение, так и уменьшение рейтинга пользователя, при этом рейтинг не падает ниже нуля. Такой рейтинг не позволит пользователю в случае неудачных действий упасть слишком глубоко (и познать мощь разгневанного Хабра). Но при этом новый пользователь и пользователь, рейтинг которого постоянно колеблется в околонулевой отметке из-за систематических “плохих” действий будут визуально выглядеть одинаково, что плохо влияет на доверие ко всей системе.

Про WoT:  Обзор платежной системы Paysafecard | SmartGambling - Cтавки на спорт

Рейтинг плюс-минус отрицательный означает, что пользовательский рейтинг может как подняться, так и упасть до любых значений. На практике смысла в большом отрицательном рейтинге нет и рекомендуется вводить в системе пороговое отрицательное значение, после которого стоит применять штрафные меры для такого пользователя, вплоть до блокировки аккаунта. При этом важно подумать и о ситуации намеренного “слива” рейтинга другими пользователями, исключить эту возможность или сделать трудно осуществимой.


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Рейтинг минус — редко используемая механика, при которой изначальный рейтинг пользователя может либо не меняться, либо уменьшаться. Не вспомню сходу проекты, в которых используется подобная механика, но теоретически она возможна. Например, для проектов или игр на выбывание, или “последних героев”.

При использовании механики рейтинга нужно не допускать важной ошибки: разрывы в количестве набранных очков между пользователями системы (или между уровнями пользователя) не должны быть демотивирующими, недостижимыми. Особенно сильно такая разница демотивирует новых пользователей, которые видят, что у них ноль очков, а у лидера рейтинга — миллионы. Почему так происходит, почему новый пользователь в такой ситуации подумает, что невозможно догнать лидера? Во-первых, новые пользователи системы еще не успели провести достаточно времени, чтобы понять динамику набора очков. Два-три миллиона очков лидера рейтинга могут быть не так уж недостижимы, если за каждое действие пользователя система начисляет тысячи очков. Проблема в том, что демотивированный новый пользователь перестает пользоваться системой раньше, чем поймет это. Во-вторых, проблема в нашем природном логарифмическом восприятии числового ряда.

Мы привыкли жить среди линейного упорядочивания чисел. Нумерация домов, рулетки и линейки, графики и часы — везде числа расположены вдоль числовой прямой на равных интервалах. Нам очевидно, что разница между 1 и 5 и между 5 и 10 одинаковая. Такая же разница между 1 500 000 и 1 500 505. На деле, линейное упорядочивание чисел — результат воздействия нашей культуры, а не способность с рождения. Наши далекие предки, жившие десятки тысяч лет назад, не имели современного математического аппарата, а числа воспринимали логарифмически. То есть, располагали их на числовой прямой все теснее по мере возрастания. Они воспринимали числа не в терминах точных значений, а оценочно-приблизительно. Это было необходимо при их образе жизни. При встрече с врагами нужно было быстро, поэтому приблизительно, оценить, кого больше — своих или чужих. Выбор, с какого дерева собирать плоды, делался тоже на основе приблизительной оценки. Наши предки не высчитывали точные значения. Логарифмическая шкала также учитывает законы перспективы и наше восприятие расстояния. Например, если мы смотрим на дерево, находящееся на расстоянии ста метров, и на другое дерево, находящееся в 100 метрах позади первого, то вторые сто метров кажутся короче.


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Играющему белыми фигурами на этой картинке не нужно знать точное количество черных фигур, чтобы понять, что его дела плохи.

Подробнее о логарифмическом восприятии чисел, о проведенных исследованиях, подтверждающих эту теорию, и о других занимательных фактах из мира математики можно прочитать в научно-популярной книге Алекса Беллоса “Алекс в стране чисел. Необычайное путешествие в волшебный мир математики”.

Логарифмическое восприятие чисел на интуитивном уровне перешло по наследству и к нам. Скрытое под культурным слоем, оно проявляет себя, например, в чувстве времени (в детстве годы проходили медленно, а сейчас просто летят). Мы по-прежнему, несмотря на все образование, теряемся при очень больших числах и инстинктивно переходим на их логарифмическое восприятие. Нам понятна разница между литром и двумя литрами пива, но что десять миллиардов, что сто миллиардов литров пива кажутся нам примерно одинаковыми числами, укладывающимися в понятие “очень-очень много пива”. Поэтому и возникает проблема ощущения недосягаемости рейтинга, если разрыв между текущей позицией и лидером составляет “очень-очень много” очков. Мозг пользователя не будет интуитивно заниматься анализом ситуации, изучать динамику накопления очков, рассчитывать время достижения вершины рейтинга. Он просто вынесет вердикт — “это очень много, не стоит тратить силы”.

Чтобы избежать появления описанных выше ситуаций, нужно применять плавающую динамику начисления очков рейтинга, при которой пользователь получает поощрения и набирать очки рейтинга в начале предполагаемого жизненного цикла использования системы быстрее, чем в середине и конце. Пример — World of Warcraft и ему подобные MMORPG с “европейской” (а не “корейской”) системой прокачки персонажа. Условная европейская система прокачки подразумевает быстрое прохождение начальных уровней игры, с последующим постепенным замедлением. Система, используемая в типичных корейских (и других азиатских) играх, предполагает резкое замедление в скорости получения последних уровней персонажа.

Например, в Lineage 2 для достижения 74 уровня нужно набрать 500 000 опыта, для 75 уровня — 560 000, для 76 уровня — 623 000, для 77 уровня уже гораздо больше — 1 175 000, а для перехода с 84 уровня на максимальный 85 уровень понадобится набрать 270 миллионов опыта, при этом скорость набора опыта почти не изменяется (вся таблица опыта и уровней в Lineage 2 доступна по этой ссылке). Такое замедление видится излишним в геймификации, так как слишком демотивирует пользователей.


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Еще один момент, о котором стоит помнить — пользователю легче забросить игру или геймифицированную систему в начале, и сложнее, когда он провел в системе много времени, после которого пользователю будет жалко бросать накопленные очки, уровни, предметы. Поэтому давайте новым пользователям временный бонус к набранным очкам, например, +50% в течение месяца. Бонус послужит дополнительным стимулом использования системы, за время действия бонуса пользователь оценит скорость набора очков, освоится и с большей вероятностью продолжит пользоваться системой.

Пример ошибки демотивирующего разрыва в рейтинге — приложение Gett Taxi. До последнего обновления в программе лояльности было двадцать уровней, для максимального требовалось 6000 очков (за одну поездку давалось в среднем 20-30 очков). Все двадцать уровней были равномерно распределены по шкале от 0 до 6000, в примерном соответствии с европейской системой прокачки в онлайн-играх. После обновления в приложение добавили еще три уровня, в 10 000, 20 000 и 40 000 очков соответственно, что ближе к корейской системе (учитывая, что количество получаемых за поездку очков не изменилось). У меня нет репрезентативной выборки по мнениям пользователей приложения об этом обновлении, но восемнадцать моих друзей и коллег, которые пользуются Gett Taxi, отметили демотивирующий эффект новых уровней рейтинга. Никто из них за прошедшее с момента обновления время (больше года) так и не получил ни одного нового уровня.


КАК Я ОЦЕНИВАЛ ХОККЕЙНЫЕ КОМАНДЫ В ИГРЕ

Разрыв между тремя новыми и предыдущими уровнями в программе лояльности Gett Taxi неоправданно большой и демотивирующий.

Чтобы избежать демотивирующего разрыва в рейтинге, нужно, кроме глобального рейтинга, добавить в систему локальные рейтинги, у которых разрывы между позициями будут не так велики.

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

Как угодно комбинируйте друг с другом перечисленные выше способы, не стесняйтесь с ними экспериментировать.

В ходе эксплуатации геймифицированной системы следите за тем, насколько рейтинг отвечает заданным при проектировании целям. Например, если целью рейтинга было увеличение доверия других пользователей к пользователям с высоким рейтингом, уделите внимание поиску и ограничению возможных честных и нечестных способов быстрого увеличения рейтинга. Основой доверительного рейтинга является сложность его получения и возможность очень быстро его утратить. Если в системе найдутся лазейки для неоправданно быстрого увеличения рейтинга, доверие к нему со стороны пользователей резко упадет. Например, если в интернет-аукционе будет возможность повышать рейтинг продавца за каждую проведенную сделку с каждым пользователем, то два пользователя могут поддерживать свой рейтинг на высоком уровне, просто покупая копеечные товары (в идеале — цифровые) друг у друга. При этом возможные негативные отзывы о некачественном сервисе или мошенничестве будут забиваться массой фейковых положительных отзывов, в результате возникает риск массовой утраты доверия к системе.

В завершение приведу еще три совета по использованию рейтинга и уровней:

В этой статье я не претендую на всеобъемлющий анализ возможных вариантов использования механики рейтинга, поэтому какие-то кейсы и варианты использования наверняка не упомянул. Если у вас есть интересный опыт использования рейтингов в играх и геймифицированных системах, поделитесь им со мной и другими читателями.

Реализация

Итак, идея есть, теперь нужно ее реализовать. Для начала нам нужны результаты игр. Без них рейтинг не посчитать. Результаты можно было бы собрать на различных спортивных сайтах автоматически или, в случае крайней необходимости, даже вручную. Но, к счастью, у сайта НХЛ есть открытое API, через которое можно получить статистические данные не только по играм, но и по командам и игрокам за всю историю существования лиги.

Для начала я выкачал данные за один сезон, сохранил их в CSV и написал простенькую консольную программку на Python, которая по этим данным рассчитывала рейтинг. Успех. Затем я выкачал результаты всех игр с 1941 года. Почему с 1941? Несмотря на то, что лига существует с 1917 года, в первые годы ее существования клубы изрядно колбасило. Многие из них исчезали, просуществовав всего несколько лет (этому поспособствовала в том числе и Великая депрессия). Более-менее стабильный состав лиги сформировался к 1942 году (начало эры Большой шестерки). Один год я прибавил для того, чтобы к 1942 рейтинги уже имели какие-то осмысленные, отличные от начальных значения. С помощью своей консольной программулины я попытался посчитать рейтинги команд, и тут вскрылся один нюанс, о котором я расскажу чуть позже.

Поскольку в итоге я хотел получить вебсайт, на котором можно будет просматривать рейтинги, нужно было выбрать стек, на котором этот сайт будет построен. Так как у меня уже была написана вышеупомянутая программа на Python, было решено писать бекэнд на ее основе. Для этого был взят Flask, т. к. очевидно Django был бы overkill для такой задачи. В качестве библиотеки для фронтенда я взял React, поскольку я хотел сделать SPA с бесшовным переходом между страницами и датами (откуда у нас несколько страниц, я покажу позже). В качестве библиотеки компонентов я взял Material UI, хотя оглядываясь назад, стоит признать, что пару табличек я мог бы и вручную сверстать, не подключая целую библиотеку.

Про WoT:  САУ M12 / World of Tanks — Игровой портал

Надо заметить, что изначально я написал просто бекэнд на Flask, отдающий статику. То есть просто html с табличкой, как в старые добрые времена. Идея разделить фронт и бэк и прикрутить на фронт React появилась позже. Примерно в то же время я для пробы написал версию бекэнда на NodeJS (Express) и обнаружил, что она обрабатывает запросы в 2-3 раза быстрее, чем версия на Flask. Таким образом я выкинул Python + Flask и внедрил NodeJS + Express. S QLAlchemy уступила место Sequelize в качестве ORM.

Скриншоты

Итак, первый скриншот. Так выглядит таблица рейтингов всех команд на 25 октября 2021 года. Мой любимый Анахайм аккурат последний, зараза. Помимо самих рейтингов мы видим как изменялись рейтинги команд за последние 7 и 30 дней (да, есть косяк с 30-дневным изменением рейтинга Сиэтла, т.к. команда новая, 30 дней назад у нее еще не было рейтинга. И пофиксить я еще это не успел). Вверху вкладки есть переключатель дат, с помощью которого можно выбрать, на какую дату показывать рейтинг.

СкриншотТаблица рейтинга на 25 октября 2021 года

Вкладка Schedule на той же основной странице. Расписание на конкретную дату. Здесь мы видим результаты, вероятности победы той или иной команды, рассчитанные на основе рейтингов команд до игры, сами рейтинги до и после игры, а также как они изменились в результате игры (и как изменились места команд в рейтинг-листе).

СкриншотРасписание на 25 октября 2021 года

Далее мы видим страницу графиков, выбран вариант за последние 5 лет. Линии команд нарисованы цветами этих команд, но в таком хаосе все равно трудно что-то разобрать. Хотя при наведении на каждую точку будет показано название команды, дата и рейтинг. К счастью есть настройка Choose visible teams, которая позволяет выбрать, какие команды отображать на графике. На втором скрине мы видим сравнение того, как изменялись рейтинги команд Anahaim Ducks (оранжевый) и Tampa Bay Lightning (синий) за последние пять лет. Согласитесь, так уже гораздо проще разобраться в графике.

Ну и последняя страница, топы. Не особо полезная, но мне придумалось, что будет забавно иметь такие данные. Здесь представлены самые большие изменения рейтингов в лучшую и худшую стороны за сезон и за календарный месяц. Прошу прощения за немного корявый скриншот. Поверьте, никакой полезной информации потеряно не было.

Выбор параметров

Теперь настало время пристальнее взглянуть, а что же происходит под капотом бекэнда. Если по простому, то при запросе на бекэнде считается рейтинг на конкретную дату и отдается. Если сложнее, то есть много нюансов. Например, как мы видели выше, при расчете рейтинга у нас есть несколько параметров, которые мы можем выбрать по своему усмотрению.

Во-первых, это начальный рейтинг. Он ни на что не влияет, так как главное значение имеет разница рейтингов, а не их абсолютная величина. Единственным моим пожеланием было чтобы рейтинги не уходили в минус. Я взял за начальный рейтинг число 1000 и, как показала практика, мог бы с таким же успехом взять, например, 500, поскольку колебания рейтингов команд на протяжении всей истории не превышали +-300 пунктов.

Во-вторых, это коэффициент K. И этот выбор уже имеет значение. Как я уже упоминал выше, от этого зависит, насколько результат каждой отдельной игры будет влиять на рейтинг команд. Я рассуждал следующим образом: рейтинг должен как можно более точно отражать силы команд. Чем меньше рейтинг меняется после игры, тем точнее он отражал силы команд до игры. Таким образом, мы можем рассчитать рейтинги команд до и после каждой игры за почти 80 лет, подставляя разные коэффициенты, суммируя при этом изменения рейтингов. Чем меньше сумма изменений — тем лучше подходит коэффициент. Чуть позже я нашел статью, автор которой предлагает такой же подход, что помогло мне убедиться, что я на верном пути. Данным методом я подобрал коэффициент K=9,2. Его я и использовал в дальнейшем для всех своих расчетов рейтинга. Таким же образом я выяснил, что более точные результаты дает подход, при котором окончание игры в овертайме (дополнительном времени) расценивается как ничья (исход игры 0,5 в рамках расчета рейтинга). Что объяснимо, т. к. если команды за основное время не смогли выявить победителя, логично предположить, что в рамках этой конкретной игры их силы примерно равны.

Я часто встречал подход, при котором при расчете рейтинга Эло в командных видах спорта к рейтингу команды, играющей дома добавляется некая поправка, так как считается, что у домашней команды есть преимущество. Я не стал применять этот подход, поскольку мне он не нравится. В конце концов, в шахматах при расчете рейтинга не делают поправку на игру белыми, и все с этим как-то живут. Также я не стал делать разные коэффициенты для игр регулярного чемпионата и плей-офф. Несомненно, игры плей-офф более важные, и команды выкладываются в них сильнее, чем в играх регулярки, но не уверен, что стоит более сильно изменять рейтинг на основе игр плей-офф.

Кроме этого, нужно упомянуть, что в межсезонье команды часто теряют одних игроков и приобретают других. Игроки по-разному проводят межсезонье и кто-то оказывается в лучшей форме, чем другие. Таким образом, рейтинги перед началом сезона (оставшиеся с прошлого сезона) не всегда точно отражают реальную силу команд в новом сезоне. В связи с этим в начале сезона (скажем, в первой четверти чемпионата) можно было бы использовать повышенный коэффициент K, чтобы рейтинги подстроились под реальную силу команд, но я не стал этого делать, чтобы не усложнять модель.

А что дальше?

Еще год назад (когда я и занимался всем вышеописанным) у меня были планы планы расширять функциональность данного сайта. Я хотел добавить больше интересных вариантов просмотра рейтинга (разбиение по конференциям и дивизионам, например), вероятности различных исходов в плей-офф, расчет сложности расписания игр для каждой команды и прочее. Также хотел перевести сайт на NextJs, чтобы был серверный рендеринг. К сожалению, энтузиазм поугас, и сейчас его едва хватает на то, чтобы поддерживать то, что есть. Если вдруг я найду время и желание, то возможно что-то и будет. Но вероятность этого не так и велика. Если кто-то дочитал досюда, большое спасибо за внимание. Кто не дочитал — тоже спасибо, но они этого не увидят 😉

Технические моменты

Те, кто дочитал до этого места, наверное, заметили, что рейтинг на конкретную дату в прошлом — величина постоянная, и будучи однажды рассчитанным, меняться уже не будет. Таким образом, можно было бы один раз рассчитать рейтинг-листы на каждый день с 1941 года по текущий момент и хранить их в базе. Но на мой взгляд, такой подход не совсем оптимален из-за большого объема таких данных. Но вариант каждый раз рассчитывать рейтинг для каждой даты с нуля тоже не очень хорош, поскольку если для расчета рейтинга на какую-либо дату в 40-х нам бы потребовалось обработать пару тысяч игр, то для расчета рейтинга на текущий момент — уже более 50 тысяч. Разница во времени расчета получалась довольно заметная (миллисекунды против сотен миллисекунд). Поэтому я пошел на компромисс. Я сохранил значения рейтинга каждой команды на момент начала каждого сезона, и промежуточные значения на любую дату внутри сезона рассчитываются не на основе всех игр с нуля, а на основе значений на начало конкретного сезона. Как вы понимаете, на результат расчета это не влияет, зато положительно сказывается на скорости.

Также помимо результата на каждую дату мне хотелось иметь графики, показывающие, как изменялись рейтинги команд со временем. Для таких графиков нужно рассчитать рейтинги через определенные промежутки времени и по этим рейтингам построить точки. В идеале это должны быть данные на каждый день, для наибольшей точности. Но если мы хотим строить график по всем командам с 1941 года по наше время, то при расчете рейтингов на каждый день мы получаем объем данных, прилетающий с бэка порядка 2-3 мегабайт. К тому же, т. к. нам нужно пройтись по каждому дню с самого начала, наши сохраненные в базе рейтинги на начало сезона становятся не особо полезными. Все равно приходится обрабатывать все игры. Таким образом, запрос обрабатывался порядка секунды, что мне категорически не нравилось. Я не рассчитывал, что у моего сайта будут тысячи пользователей, но всё равно такой расклад меня не особо устраивал. Сначала я решил использовать Redis для кеширования запросов к этому endpoint’у. Первый запрос за день рассчитывался с нуля, далее результат кешировался, и все последующие запросы отдавались уже за ~20 миллисекунд. Шикарно. Но по итогу я всё равно отказался от этой идеи. Я решил, что разрешение в один день на графике за 80 лет абсолютно ни к чему. Сейчас на моем сайте доступно 5 вариантов графика: за последние 30 дней, за год, за 5 лет, 10 лет и за всё время. И если график за 30 дней имеет разрешение 1 день, то график за всё время — полгода. Да, с таким разрешением теряются некоторые экстремумы, которые пришлись до или после расчетной точки. Но я решил, что это приемлемо. Напишите в комментариях ваше мнение на этот счет.

Ах да, забыл самое главное. Как всё это дело обновляется. Просто обновляется. Написан скриптец, который делает запрос к вышеупомянутому API НХЛ и получает данные о свежесыгранных матчах. Скриптец дергается кроном несколько раз за ночь (время начала матчей колеблется от 7:30 вечера до 6:30 утра по Москве, так что я предпочитаю делать обновления несколько раз за игровой день).

Оцените статью
TankMod's
Добавить комментарий