Как создать алгоритм матчинга анкет, немного похожий на Леонардо Дай Винчик и Tinder
Пишу бота для Telegram на Python (библиотека aiogram с asyncio), функционал которого чем-то схож с Леонардо Дай Винчик или Tinder. Пользователь начинает поиск и ему поочередно выдаются анкеты из БД. Он может либо "лайкнуть" анкету, либо "дизлайкнуть". Соответственно, когда симпатия взаимна, обоим пользователям отправляется контакт для связи (и так далее).
Модели в БД выглядят следующим образом:
Модель пользователя:
class User(BaseModel):
id = PrimaryKeyField() # Постоянный Telegram ID
mention = CharField(unique=True, null=True) # Упоминание пользователя в виде @diplomente :)
phone = CharField(null=True) # TG - Contact
name = CharField(null=False) # По-умолчанию предлагается имя Telegram профиля, но пользователя может сменить
age = IntegerField() # Возраст в цифрах
city = CharField(default="Душанбе")
photo = IntegerField() # ID фотографии профиля. Значение только храниться в БД.
gender = CharField(max_length=1) # M - Male, F - Female
search_gender = CharField(max_length=1) # M - Male, F - Male, B - Both
description = CharField() # Описание профиля, информация о себе и цели поиска
Модель симпатий:
class Mutuality(BaseModel):
first = ForeignKeyField(User)
second = ForeignKeyField(User)
status = BooleanField(default=0) # 0 - дизлайк, 1 - симпатия
# Когда отправляется симпатия, создается запись в БД, где first - тот, кто отправил симпатию, second - тот, кому она
# направлена.
Теперь столкнулся со сложностями при реализации:
- Как реализовать алгоритм поиска следующей анкеты?
- Как избежать дубликатов (повторные отображения анкет, к примеру, ранее друг друга "дизлайкнувших" или друг друга "лайкнувших" и так далее)?
И какие у вас будут советы и рекомендации? Спасибо!
Ответы (2 шт):
Создайте список, где находится информация по существующим активным анкетам, например это будет список кортежей. После этого создайте Хендлер next_user, при помощи машины состояний конечного автомата присвойте ему состояние актив, когда пользователь просматривает другие анкеты. Функция будет обрабатывать входящее сообщение в виде сердечка или дислайка, брать рандомный элемент из нашего списка анкет, отображать данную анкету и удалять ее из нашего списка.
Список определите, как глобальную переменную, однако исключите возможность возникновения асинхронности, путём инициализации списка внутри вашей функции-обработчика.
Вот и весь алгоритм. Ничего сложного.
Чтобы избежать дубликатов как предложение - создать еще одну таблицу с историей действий (когда один другого лайкнул/дизлайкнул/ответил взаимностью)
Далее при выводе потенциально интересной анкеты пользователю можно выводить все, за исключением тех, что уже есть в таблице с действиями.
P.s. дабы избежать переполнения этой таблицы можно периодически очищать действия более ~недельной давности