shamhi / HamsterKombatBot

Bot that mines coins in HamsterKombat
Apache License 2.0
438 stars 130 forks source link

[Предложение] Логика покупки комбо карт #251

Open XPacL opened 2 weeks ago

XPacL commented 2 weeks ago

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

n1tr0g3n4ik commented 2 weeks ago

Еще бы добавить возможность через кфг выбирать на какой сессии делать фарм денег и карточек, либо же только денег, или только карточек (как то так, хз)

VintaGist commented 2 weeks ago

@shamhi, во первых, спасибо за добавление возможности автопокупки комбо и кодов морзе! Это круто, безусловно.

Во вторых, текущий алгоритм работает так: запускаем бота, он смотрит что нужно купить 3 карты для активации комбо бонуса, но покупает только то, что может (это может быть одна, 2 или 3 карточки по разным причинам) и запрашивает получение бонуса.

При неполной покупке получаем похожее сообщение:

Unknown error while Claim Daily Combo: 400, message='Bad Request', url=URL('https://api.***.io/clicker/claim-daily-combo') | Response text: {"error_code":"DAILY_COMBO_NOT_READY","error_message":"DailyComboNotReady combo...

К тому же бот при повторном запуске покупает снова тот же набор, не "зная" о том что он уже купил эту карту в текущем бонусном раунде

Почему мы не всегда можем купить 3 карты - недостаточный баланс, карта имеет время на восстановление и сейчас не активна, карта зависима от прокачки уровня другой карты либо от количества рефераллов

Поэтому, предлагаю улучшить текущий алгоритм автозакупки комбо-карточек:

Для этого нам нужно:

  1. Проверить, все ли карты мы сможем купить
  2. "Вспомнить", какие карты УЖЕ куплены в текущем бонусном раунде, чтоб не покупать их снова.
  3. Вывести уведомление пользователю что автозакупка невозможна, если это так
  4. Не делать приоритетной закупку карточек, если впоследствии все равно невозможно собрать комбо

на момент написания этого сообщения код из диапазона https://github.com/shamhi/HamsterKombatBot/blob/0ca5159d1689e5a2debf2354d9a8f776bcf2a8d1/bot/core/tapper.py#L428C1-L450C84 выглядит так:

                        is_claimed = daily_combo['isClaimed']

                        if not is_claimed:
                            combo_cards = await self.get_combo_cards(http_client=http_client)

                            cards = combo_cards['combo']
                            date = combo_cards['date']

                            available_combo_cards = [
                                data for data in upgrades
                                if data['isAvailable'] is True
                                   and data['id'] in cards
                                   and data['isExpired'] is False
                                   and data.get('cooldownSeconds', 0) == 0
                                   and data.get('maxLevel', data['level']) >= data['level']
                                   and (data.get('condition') is None
                                        or data['condition'].get('_type') != 'SubscribeTelegramChannel')
                            ]

                            if date == datetime.now().strftime("%d-%m-%y"):
                                common_price = sum([upgrade['price'] for upgrade in available_combo_cards])

                                if common_price < bonus and balance > common_price:

Заменить код предлагаю на такой:

from datetime import datetime, timedelta
....

                        is_claimed = daily_combo['isClaimed']
                        upgraded_list = daily_combo['upgradeIds']# уже обновлены:

                        if not is_claimed:
                            combo_cards = await self.get_combo_cards(http_client=http_client)

                            cards = combo_cards['combo']
                            date = combo_cards['date']

                            available_combo_cards = [
                                data for data in upgrades
                                if data['isAvailable'] is True
                                   and data['id'] in cards # есть в перечне комбо
                                   and data['id'] not in upgraded_list # уже обновлены ранее в этом же периоде комбо
                                   and data['isExpired'] is False
                                   and data.get('cooldownSeconds', 0) == 0
                                   and data.get('maxLevel', data['level']) >= data['level']
                                   and (data.get('condition') is None
                                        or data['condition'].get('_type') != 'SubscribeTelegramChannel')
                            ]

                            start_bonus_round = datetime.strptime(date, "%d-%m-%y").replace(hour=15)
                            end_bonus_round = start_bonus_round + timedelta(days=1)

                            if start_bonus_round <= datetime.now() < end_bonus_round:
                                common_price = sum([upgrade['price'] for upgrade in available_combo_cards])
                                need_cards_count = len(cards)
                                possible_cards_count = len(available_combo_cards)
                                is_combo_accessible = need_cards_count == possible_cards_count

                                if not is_combo_accessible:
                                    logger.info(f"{self.session_name} | "
                                                    f"<r>Daily combo is not applicable</r>, you can only purchase {possible_cards_count} of {need_cards_count} cards")

                                if balance < common_price:
                                    logger.info(f"{self.session_name} | "
                                                    f"<r>Daily combo is not applicable</r>, you don't have enough coins. Need <y>{common_price:,}</y> coins, but your balance is <r>{balance:,}</r> coins")

                                if common_price < bonus and balance > common_price and is_combo_accessible:

Прошу иметь ввиду такая реализация напишет пользователю Daily combo is not applicable, you can only purchase 0 of 3 cards даже в том случае если он уже купил 1 или 2 необходимые карточки из трех. Возможно этот текст нужно изменить на что-то вроде Не все карточки вы можете купить...

AntonVlk commented 2 weeks ago

Также бот игнорирует лимит по балансу. Т.е. если снижение баланса ограничено на 1кк, а карточка из комбо стоит 200к, то он все равно ее купит.

VintaGist commented 2 weeks ago

Т.е. если снижение баланса ограничено на 1кк, а карточка из комбо стоит 200к, то он все равно ее купит.

Да, игнорирует. Автозакупка сработает по сути так, чтоб потраченные деньги не превысили сумму бонуса. Поэтому в таком виде вроде как и неважно временное снижение баланса ниже ограничения, т.к. сумма компенсируется бонусом.

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

ZakezMine commented 2 weeks ago

очень хороша идея реализации закупки карт для комбо 5кк , надеемся что его добавят в некст обнове

ImMagnat commented 2 weeks ago

@shamhi, приветсвую, интересное решение с покупками. Предлагаю небольшое улучшение:

........... from datetime import datetime, timedelta

now = datetime.now() yesterday = now - timedelta(days=1) if date == now.strftime("%d-%m-%y") or date == yesterday.strftime("%d-%m-%y"): ...........

сейчас проверка выглядит так if date == datetime.now().strftime("%d-%m-%y"):

В чем соль, когда мы получаем date (условно 08-06-24) после 12 ночи проверка не пройдет, и если у нас баланс набрался только к утру, мы не сможем приобрести карточки комбо, ибо datetime.now() будет 09-06-24

P.S. можно было инлайн написать (просто читабельней по степам)

VintaGist commented 2 weeks ago

Предлагаю небольшое улучшение

Спасибо что обратил внимание, но тогда уж смотрим на время (с 15:00 до 15:00)

from datetime import datetime, timedelta
....

start_bonus_round = datetime.strptime(date, "%d-%m-%y").replace(hour=15)
end_bonus_round = start_bonus_round + timedelta(days=1)

if start_bonus_round <= datetime.now() < end_bonus_round:

PS. Обновил сообщение выше

Kit0077 commented 2 weeks ago

@shamhi, во первых, спасибо за добавление возможности автопокупки комбо и кодов морзе! Это круто, безусловно.

Во вторых, текущий алгоритм работает так: запускаем бота, он смотрит что нужно купить 3 карты для активации комбо бонуса, но покупает только то, что может (это может быть одна, 2 или 3 карточки по разным причинам) и запрашивает получение бонуса.

При неполной покупке получаем похожее сообщение:

Unknown error while Claim Daily Combo: 400, message='Bad Request', url=URL('https://api.***.io/clicker/claim-daily-combo') | Response text: {"error_code":"DAILY_COMBO_NOT_READY","error_message":"DailyComboNotReady combo...

К тому же бот при повторном запуске покупает снова тот же набор, не "зная" о том что он уже купил эту карту в текущем бонусном раунде

Почему мы не всегда можем купить 3 карты - недостаточный баланс, карта имеет время на восстановление и сейчас не активна, карта зависима от прокачки уровня другой карты либо от количества рефераллов

Поэтому, предлагаю улучшить текущий алгоритм автозакупки комбо-карточек:

Для этого нам нужно:

  1. Проверить, все ли карты мы сможем купить
  2. "Вспомнить", какие карты УЖЕ куплены в текущем бонусном раунде, чтоб не покупать их снова.
  3. Вывести уведомление пользователю что автозакупка невозможна, если это так
  4. Не делать приоритетной закупку карточек, если впоследствии все равно невозможно собрать комбо

на момент написания этого сообщения код из диапазона https://github.com/shamhi/HamsterKombatBot/blob/0ca5159d1689e5a2debf2354d9a8f776bcf2a8d1/bot/core/tapper.py#L428C1-L450C84 выглядит так:

                        is_claimed = daily_combo['isClaimed']

                        if not is_claimed:
                            combo_cards = await self.get_combo_cards(http_client=http_client)

                            cards = combo_cards['combo']
                            date = combo_cards['date']

                            available_combo_cards = [
                                data for data in upgrades
                                if data['isAvailable'] is True
                                   and data['id'] in cards
                                   and data['isExpired'] is False
                                   and data.get('cooldownSeconds', 0) == 0
                                   and data.get('maxLevel', data['level']) >= data['level']
                                   and (data.get('condition') is None
                                        or data['condition'].get('_type') != 'SubscribeTelegramChannel')
                            ]

                            if date == datetime.now().strftime("%d-%m-%y"):
                                common_price = sum([upgrade['price'] for upgrade in available_combo_cards])

                                if common_price < bonus and balance > common_price:

Заменить код предлагаю на такой:

from datetime import datetime, timedelta
....

                        is_claimed = daily_combo['isClaimed']
                        upgraded_list = daily_combo['upgradeIds']# уже обновлены:

                        if not is_claimed:
                            combo_cards = await self.get_combo_cards(http_client=http_client)

                            cards = combo_cards['combo']
                            date = combo_cards['date']

                            available_combo_cards = [
                                data for data in upgrades
                                if data['isAvailable'] is True
                                   and data['id'] in cards # есть в перечне комбо
                                   and data['id'] not in upgraded_list # уже обновлены ранее в этом же периоде комбо
                                   and data['isExpired'] is False
                                   and data.get('cooldownSeconds', 0) == 0
                                   and data.get('maxLevel', data['level']) >= data['level']
                                   and (data.get('condition') is None
                                        or data['condition'].get('_type') != 'SubscribeTelegramChannel')
                            ]

                            start_bonus_round = datetime.strptime(date, "%d-%m-%y").replace(hour=15)
                            end_bonus_round = start_bonus_round + timedelta(days=1)

                            if start_bonus_round <= datetime.now() < end_bonus_round:
                                common_price = sum([upgrade['price'] for upgrade in available_combo_cards])
                                need_cards_count = len(cards)
                                possible_cards_count = len(available_combo_cards)
                                is_combo_accessible = need_cards_count == possible_cards_count

                                if not is_combo_accessible:
                                    logger.info(f"{self.session_name} | "
                                                    f"<r>Daily combo is not applicable</r>, you can only purchase {possible_cards_count} of {need_cards_count} cards")

                                if balance < common_price:
                                    logger.info(f"{self.session_name} | "
                                                    f"<r>Daily combo is not applicable</r>, you don't have enough coins. Need <y>{common_price:,}</y> coins, but your balance is <r>{balance:,}</r> coins")

                                if common_price < bonus and balance > common_price and is_combo_accessible:

Прошу иметь ввиду такая реализация напишет пользователю Daily combo is not applicable, you can only purchase 0 of 3 cards даже в том случае если он уже купил 1 или 2 необходимые карточки из трех. Возможно этот текст нужно изменить на что-то вроде Не все карточки вы можете купить...

Привет! Я так понимаю, скрипт не будет покупать комбо карты если сумма покупки выше суммы бонуса(5кк)? Но это же бессмысленно, потому, что комбо нужны не для прокачки, а для проявления активности, за которую потом вознаградят при дропе.

Kit0077 commented 2 weeks ago

Daily combo is not applicable, you can only purchase 0 of 3 cards

Я постоянно получаю ошибку в виде Daily combo is not applicable, you can only purchase 0 of 3 cards. На аккаунте, в котором вручную могу спокойно купить комбо. В чем может быть проблема?

ButCheR-PRO commented 1 week ago

@Kit0077 предлагал добавить возможность автоматически покупать комбо, даже если затраты будут превышать бонус (5 миллионов). Вот решение: В bot/core/tapper.py на 164 строке прописана такая логика: if common_price < bonus and balance > common_price and is_combo_accessible: То есть, если затраты на покупку комбо меньше чем бонус комбо (5кк) И ваш баланс больше чекм затраты на покупку комбо И комбо доступно, то начать процесс покупки. Но эту логику можно изменить, убрав условие if common_price < bonus. В итоге строчка будет выглядеть так: if balance > common_price and is_combo_accessible:

Но тогда могут быть огромные расходы на покупку комбо. Я бы предложил регулировать значение расходов, задав лимит, например ЕСЛИ сумма затрат на комбо МЕНЬШЕ 20 миллионов: if common_price < 20000000 and balance > common_price and is_combo_accessible:

Можно даже вынести это значение в конфиг, чтоб регулировать его из файла .env. Делается это так: if common_price < settings.MAX_COMBO_PRICE and balance > common_price and is_combo_accessible: И в bot/config/config.py добавить: MAX_COMBO_PRICE: int = 20000000 и в .env прописать: MAX_COMBO_PRICE=20000000