Topic 6 of 6

Course materials are currently available in Russian only.

Бот-викторина

Соберём всё вместе — вопросы, проверку ответов, очки и итоговую таблицу — в бота-викторину.

Честная проверка ответов

Игроки пишут ответы как угодно: «Меркурий», «меркурий!», « МЕРКУРИЙ». Поэтому и правильный ответ, и ответ игрока сначала нормализуют:

import re


def normalize(text):
    text = text.lower().replace("ё", "е")
    return " ".join(re.findall(r"\w+", text))
  • lower() до замены «ё» — иначе заглавная «Ё» не заменится;
  • re.findall(r"\w+", …) оставляет только слова — знаки препинания и лишние пробелы исчезают;
  • слова соединяют одним пробелом, а не склеивают: иначе «1945 год» совпадёт с «1945год».

Состояние игры

Бот может играть одновременно в разных каналах и на разных серверах. Поэтому состояние хранят по каналу:

GAMES = {}        # номер канала → {"index": …, "open": …}
game = GAMES.setdefault(message.channel.id, {"index": -1, "open": False})

Флаг open закрывает вопрос после первого правильного ответа — очко получает самый быстрый. Очки игроков храните по author.id.

Чтобы данные переживали перезапуск бота, их сохраняют в файл (JSON) или базу (SQLite).

Места

Места с ничьими считают так: место = 1 + число игроков, у которых очков больше. Тогда равные игроки делят место, а следующее учитывает всех, кто выше:

place = 1 + sum(1 for s in SCORES.values() if s > score)

Для очков 5, 5, 3, 1 получится 1, 1, 3, 4.

Запуск на сервере

Чтобы бот работал, пока ваш компьютер выключен, его запускают на сервере (VPS) или в облаке — так же, как Telegram-ботов. Токен передают через переменную окружения DISCORD_TOKEN, а не пишут в код.

Итог

  • нормализация ответов: lower, «ё» → «е», \w+, один пробел;
  • состояние по channel.id, очки по author.id, вопрос закрывается после первого верного;
  • места с ничьими: 1 + число игроков выше;
  • итог в эмбеде.