Рейтинг Elo в играх для двух игроков

    Раньше наш рабочий процесс прерывался из-за ряда неразрешенных вопросов:

    • А кто из нас лучше всех играет в настольный футбол?
    • С кем бы мне сейчас пойти поиграть?
    • Кого надо уволить, потому что он не работает а только играет?

    Наш опыт решения данных вопросов с помощью системы рейтинга Elo будет рассмотрен в статье. А также ссылка на репозиторий и на сайт будут разбросаны по статье.

    Когда компания маленькая, а игроков еще меньше, то вопрос лучшего решается простым проведением турнира в пятницу вечером раз в пару месяцев. <совет>Шикарнейший повод выпить за счет компании.</совет>(Мы по неопытности это не сразу поняли. И сначала просто так играли.) Но компания растет, лига тоже увеличивается, и вот уже отыграть турнир, даже с учетом предварительного разбиения на группы, становится очень сложно. Это просто физически тяжело на большом футбольном столе провести 15 партий за вечер.

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

    Про Elo


    Разработал систему американский профессор физики и шахматист Арпад Эло.

    Каждый новый игрок обычно получает рейтинг 1400. На самом деле не принципиально сколько. По итогам каждого матча часть рейтинга переходит от одного игрока к другому. И чтобы не уходить в минус берется изначально с запасом.

    Будем считать, что игрок A в случае выигрыша получает 1 очко, в случае поражения — 0, а при ничьей — 0.5. Назовем эту переменную Sa.

    Введем ожидаемое количество очков(Ea), которое игрок A получит за игру:

    Ea = 1 / (1 + 10^((Rb-Ra)/400))

    где Rb и Ra — это текущий рейтинг игроков B и A соответственно. Ea принадлежит интервалу (0, 1).

    Коэффициенты подобраны таким образом, чтобы при разнице в рейтинге в 200 пунктов, ожидаемое количество очков равнялось приблизительно 0.75. Новый рейтинг игрока A считаем по формуле:
    Ra’ = Ra + K * (Sa — Ea)

    где K — коэффициент. Это максимальное количество пунктов рейтинга, который игрок может получить/потерять за одну игру. Обычно равняется 16. В ФИДЕ зависит от уровня игроков и варьируется от 10 до 30.

    Аналогично считается рейтинг второго игрока Rb'.

    Очевидно, что Ea + Eb = 1, Sa + Sb = 1 и следовательно Ra’ — Ra + Rb’ — Rb = 0, то есть у нас игра с нулевой суммой. Из формул видно, что сильный игрок за победу над слабым игроком получает меньше рейтинга, чем если слабый выиграет у сильного.

    Мы рейтингом пользуемся уже около года. Отыграли более тысячи матчей. По моему субъективному мнению рейтинг отображает достаточно точно расстановку игроков в текущий момент времени. Как только кто-то в компании начинает играть лучше, например освоив удар, в течение недели занимает соответствующее место в рейтинге.

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

    После введения рейтинга сильно изменилось поведение во время игры. Матчи стали зрелищней. Если раньше, пропустив пару мячей в начале, проще было уже слить этот матч и начать новый, то теперь есть стимул биться до конца, чтобы не потерять (или не подарить сопернику) очки рейтинга! Автор статьи недавно проигрывал 1:6. А выиграл 7:6. Это был жаркий матч.

    Естественно, когда мы решили попробовать рейтинг, первым делом поискали готовые реализации. И хотя многие онлайн игры используют Elo, не нашли ничего толкового, где бы мы могли просто заносить результаты наших игр. Поэтому в пятницу вечером был накидан google-скрипт для google-доков.

    Пол года назад захотелось посмотреть на Asp.Net Core в действии(тогда RC1 был). И объективно google-скрипта уже давно не хватало. А там как раз выходные были. В итоге появилась система рейтинга, которой мы успешно пользуемся до сих пор. Нам нравится. Мне точно, а остальные может боятся сознаться, что нет.

    Я думаю будет правильным поделиться со всеми. Исходники доступны здесь.

    Получилось что-то явно большее чем просто MVP. В том числе сейчас реализовано:

    • Подсчет рейтинга Elo;
    • Дополнительная статистика: соотношение побед, забито/пропущено, победы и поражения подряд;
    • Подсчет очков получаемых/теряемых в случае победы/поражения при игре с конкретным игроком в следующем матче. Надо же как-то планировать с кем лучше сейчас играть;
    • Импорт результатов матчей из csv. Это мы с google-скриптов переезжали;
    • Аутентификация с поддержкой OAuth. Пока только google, так как нам хватает. Но добавить еще какую систему несложно;
    • Упрощенная система прав доступа. Существует админ лиги с возможностью управлять лигой и просто игроки;
    • Приглашение новых пользователей. С уведомлением по емеил;
    • Раздельные лиги. Каждый пользователь может создать свою приватную лигу, которая будет видна только игрокам лиги;
    • Поддержка двух языков: английского и русского. У меня давнишние счеты с локализацией приложений. И сильно хотелось посмотреть как это реализовано в Asp.Net Core;
    • Адаптивный дизайн. Ничего сверх естественного. Просто Bootstrap. Чтобы удобно было заносить результаты с телефона;
    • Должно работать с выключенным JavaScript. Удобнее конечно с включенным. Но так как было желание посмотреть на некоторые фичи именно MVC, то получилось многостраничное приложение.

    Во время разработки для хостинга я использовал Azure. Будучи уверенным, что потом спокойно перееду на какой-нибудь хостинг. Так уж и быть, даже оплачу его. И попытался переехать… Даже был морально готов заплатить баксов 50 в год за самый скромный вариант. Но когда я провозился сначала день с миграцией базы, а потом еще и не завелся проект, потому что хостер не очень-то готов к Asp.Net Core, вынужден был остаться на Azure. Но ценник там большой. А с другой стороны есть с чем сравнивать, Azure значительно удобнее.

    Вспомнилась реклама на Хабре про хостинг Azure для стартапов. Почитал условия. Написал жалобное письмо на указанный емеил. И проект добавили в программу поддержки стартапов. Надеюсь, после статьи не исключат. Хотя я считаю, что проект всем требованиям удовлетворяет. В итоге, вопрос с хостингом теперь решен на 3 года! Так что если кто не хочет разворачивать проект локально, присоединяйтесь к нам, создавайте свою лигу. Экспериментально было установлено, что название не очень запоминающееся. Поэтому мы общим голосованием решили использовать learningstreet.ru.

    Захватывающая история почему именно LearningStreet
    Давным давно один наш коллега, верстая подпись к письму, написал в шутку адрес офиса как learning street 79 (Учебная улица). Мы посмеялись. А буквально день спустя я назвал ряд ребят «пацанами с которыми мы работаем»(в негативном контексте), а не друзьями. Слово за слово и вспомнилась цитата героя фильма Волк с Уолл-стрит: «это Уолл-стрит. Здесь нет друзей». Которая была модифицирована в «это Лёнинг-стрит. Здесь нет друзей». С тех пор, если кому-то кажется что мир к нему неоправданно жесток в пределах нашего офиса, мы вспоминаем про Лёнинг-стрит. То есть каждый день. Собственно в рейтинге по футболу у нас друзей тоже нет и пощады ждать не стоит.

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

    Ах да, чуть не забыл. Кого надо уволить? Судя по всему меня:

    Support the author
    Share post

    Comments 29

      +2
      А подробнее про правила, по которым идёт игра? Длительность матча? Забавные истории?
        +1
        Для рейтинга важно лишь чтобы была возможно определить кто победил или ничью. Мы играем до 7 голов. Но можно играть и по времени. А вообще мы стараемся придерживаться вот этих правил — http://rbk.moy.su/rules/short-rules.pdf
        И рейтинг, кстати, необязательно использовать для футбола. Отлично подойдут любые игры для двух: теннис, го.

        Про забавные истории я подумаю :)
          0
          Мы играем до 7 голов
          Вот мой взгляд как раз за число 7 и зацепился, потому и спросил.
          И сколько же в итоге длится матч в среднем?
          Не пробовали анализировать матчи разных игроков с одинаковым счётом по длительности? У кого сколько времени уходит на забитие гола? Понимаю, что это всё ситуационно, но может есть какая-то корреляция с уровнем игрока?
            0
            Глубокого анализа мы не делали. Хотя переодически возникает такое желание. Опишу свои ощущения по времени игры.
            Матч в среднем 5-10 минут. Но если столкнутся два сильных игрока, играющих от обороны, и в воинственном настроении, то можно дотянуть до 15-20. Скорее всего время матча коррелирует со стилем игры. На превью, кстати, фотография нашего стола. И там видно, что игроки широкие. В результате, с первой линии в ворота забить непросто, потому что вратарь и защитники очень хорошо закрывают ворота. Нужно делать какую-нибудь комбинацию, разыгрывать мяч на первой линии, чтобы обмануть соперника. Либо очень популярно рандомом от борта из своей обороны.
            Мы еще практикуем играть двое на двое. Тогда один игрок встает только на защиту, второй только на нападение. И такие матчи переваливали у сильных игроков за пол часа. И это было больше испытание на износ. Потому что слегка наклонившись(большинство парней высокие) простоять пол часа — физически сложно.
              0
              <совет>Шикарнейший повод выпить за счет компании.</совет>
              Скорее всего время матча коррелирует со стилем игры.
              А с алкоголем в крови? Во время турниров нет какой-то хитрой тактики, построенной на интригах и доливании?
                –1
                На второй турнир я принес бутылку вискаря со словами «мне трезвые соперники не нужны». Но не прокатило. У нас к турнирам очень серьезно относятся и на такой слабый развод не ведутся. Разве что слегка снять напряжение. Кстати, да, во время турнира очень сильно меняется поведение. Из-за переживаний тяжело делать что-то натренированное и сводится все к удару посильнее. Алкоголь скорее после турнира или для зрителей.

                Еще очень популярен способ выигрыша — вывести соперника из себя подколами, поддевками. Так что игра тренирует еще и стойкость к язвительным комментариям.
            0
            «Для рейтинга важно лишь чтобы была возможно определить кто победил или ничью.»
            то есть 7:0 и 7:6 — это одинаково влияет на рейтинг? IMHO не совсем верно…
              0
              Ниже предложили модификацию — https://habrahabr.ru/post/308920/#comment_9785216. И она мне нравится
          +1
          За теорию, спасибо конечно, но код…
          Логика в контроллерах, станная структура проекта и можно продолжать дальше, если, конечно, вашей целью не было накидать небольшой прототип.
          Про Unit тесты сто раз уже говорили, что вы фактически тестирутете функционал EntityFramework, у которой есть свои юнит-тесты.
          Или вы ей не доверяете?
            0
            Я очень положительно отношусь к критике. Постараюсь использовать ее, чтобы стать лучше как специалист. Поэтому не могли бы вы более подробно расписать ваши претензии с объяснениями, чем это плохо? А то сейчас вы как-то необоснованно набросили. Спасибо :)

            Про Unit тесты сто раз уже говорили, что вы фактически тестирутете функционал EntityFramework, у которой есть свои юнит-тесты.

            1) Мне кажется вы невнимательно читали. Иначе бы у вас были более серьезные претензии ;)
            2) Конкретно где там в юнит тестах тестируется EF
            0
            попробуйте параллельно внедрить glicko2 как эволюцию эло и первого глико.
            Система отличается добавлением двух параметров — отклонением рейтинга и его волатильностью, за счет чего: а) мы можем сказать насколько рейтинг игрока реален на текущий момент (очевидно, что рейтинг игрока, сыгравшего менее 5 матчей еще не стабилизирован и не доверителен), б) рейтинг игрока намного быстрее стабилизируется, чем рейтинг по эло.
              0
              Мы пробовали glicko2. Не понравилось. Мне кажется, что в glicko2 очень важно, чтобы игроки играли примерно одинаковое количество матчей. Нам тяжело этого достичь.
                0
                как раз наоборот. глико менее важно кол-во матчей, чем эло. плюс он практически не подвержен такому https://habrahabr.ru/post/308920/#comment_9784950 чем меньше матчей сыграл игрок, тем сильнее будет колбасить его рейтинг, и тем быстрее он найдет именно свой рейтинг. Соответственно соперники получают разное кол-во баллов за игру (сумма не равна 0), что опять же более справедливо — по-разному оценивать соперников. В эло в расчет принимается только сила соперника (по факту разница в рейтингах), в глико же кол-во матчей с начала «карьеры» и стабильность. Если эло-игроку понадобиться матчей 10, чтобы добраться с 1400 (как я понял, ваш дефолт) до своих 2000 очков, на которых его рейтинг стабилизируется, то глико-игроку понадобиться матча 3. (цифры условные, примерные, следующие из многолетнего опыта увлечения подобными рейтингами).
              0
              Кому-то удалось забраться на пятое место, достойно проиграв (со счётом 3:7) всего в одном матче, забавно.
                0
                А вы внимательный :) Есть такой маленький недостаток у эло. Если игрок сыграл мало матчей, то он будет очень близок к стандартному рейтингу 1400. И его положение необоснованно. Теоретически можно прятать игроков, отыгравших мало матчей.
                  0
                  на самом деле это не маленький недостаток, а достаточно большой. Рейтингов существует очень много, и они все показывают похожую точность (на достаточной базе). Вся соль именно в «тюнингах» — как быстро рейтинг будет реагировать на сторонние обстоятельства (точный рейтинг со старта, временная инфляция, другие уточняющие показатели). Эло был одним из первых рейтингов, основанных не на фиксированных очках, и оттого самым «дубовым», хоть и на голову выше традиционных очковых рейтингов.
                0
                Подсчет очков получаемых/теряемых в случае победы/поражения при игре с конкретным игроком в следующем матче. Надо же как-то планировать с кем лучше сейчас играть;

                Как лучше организовать вычисление шансов для каждого соперника, с учетом последних результатов. Чтобы при прочих равных играть с тем, против кого 000111, а не тем, против кого 111000? И потом шанс соотнести с получаемыми очками, для того чтобы получился ранкинг пригодный для накопления Эло. Есть идеи/решения?
                  0
                  Надеюсь, я правильно понял ваш вопрос.
                  На самом деле, каждый игрок интуитивно оценивает вероятность победы над конкретным игроком в данный момент времени. И может посмотреть сколько он очков получит/потеряет в случае победы/поражения и на основе этого принять решение.

                  Интуитивное представление можно вполне формализовать. Посчитав, например, количество побед/поражений за последние матчей 10. И на основе этого посчитать мат ожидание получаемых очков.
                  0
                  А когда 2х2 играете, как идет подсчет рейтинга для каждого игрока?
                    0
                    Сейчас рейтинг для двух не считаем. Раньше пробовали считать для команд. Но есть проблема, что команд получается очень много. Фактически, комбинация всех возможных вариантов 2х игроков из компании. То есть для маленькой компании еще ок, но как начинается рост количества игроков, то уже совсем неинтересно. И я согласен, что надо пытаться вводить рейтинг для каждого командного игрока, но удачного ничего придумать не получилось
                    0
                    а при ничьей — 0.5.

                    По Вашим правилам ничья возможна?
                      0
                      По нашим — нет. Но система вполне допускает, что будут заноситься матчи с результатом — ничья. Вдруг, кто играет по времени, а не до конкретного счета.
                      +1
                      Мы используем рейтинг Эло для подсчёта индивидуальных рейтингов игроков в реальном футболе (который бегать-мяч-поле-команда). Используем модификацию для футбола https://ru.wikipedia.org/wiki/Футбольный_рейтинг_Эло. В ней учитывается разница мячей, так что игра идёт не только за победу, но и буквально за каждый мяч.
                        0
                        забавно, как раз 2 года назад на ASP.NET MVC написали прилагу с рейтингом эло для кикера. Я аж сначала подумал, что кто-то из наших запостил, настолько похоже ))
                          0

                          Рейтинг Glicko получше будет

                            +1

                            Интересно, как изменится распределение рейтинга, если все константы в формуле


                            Ea = 1 / (1 + 10^((Rb - Ra)/400))

                            заменить на натуральные, а изначальный рейтинг игроков положить равным 0? Ну т.е. 10 заменить на e, а коэффициент 400 вообще убрать:


                            Ea = 1 / (1 + e^(Rb - Ra))
                            Ra’ = Ra + (Sa - Ea)
                              0
                              Вы описали логистическую кривую для Ea. Я думаю что ее как раз брали за основу. И идейно ничего не поменялось. И там и там для подсчета используется сигмоида.

                              Но все-таки совсем без коэффициентов не получится. Как я писал, для Эло коэффициенты подобраны таким образом, чтобы у игрока с преимуществом в 200 пунктов вероятность победы была приблизительно .75. Пример: игрок, одержавший 25 побед подряд над игроками его уровня, с вероятность .75 одержит победу над игроком среднего уровня.

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

                              А зачем эта искусственная информация? В "натуральной" формуле тоже будут какие-то пункты и вероятности, но надо считать.

                                0
                                Человекочитаемый формат.

                              Only users with full accounts can post comments. Log in, please.