diff --git a/src/pyclashbot/__main__.py b/src/pyclashbot/__main__.py index 24c866adc..8e685a775 100644 --- a/src/pyclashbot/__main__.py +++ b/src/pyclashbot/__main__.py @@ -49,6 +49,14 @@ def make_job_dictionary(values: dict[str, str | int]) -> dict[str, str | int]: Returns: A dictionary of job toggles and increments based on the values of the GUI window. """ + print("values in job_dict:\n") + print( + "free_offer_user_toggle:", + values["free_offer_user_toggle"], + "gold_offer_user_toggle:", + values["gold_offer_user_toggle"], + ) + jobs_dictionary: dict[str, str | int] = { # job toggles "open_chests_user_toggle": values["open_chests_user_toggle"], @@ -56,6 +64,7 @@ def make_job_dictionary(values: dict[str, str | int]) -> dict[str, str | int]: "donate_toggle": values["donate_toggle"], "card_mastery_user_toggle": values["card_mastery_user_toggle"], "free_offer_user_toggle": values["free_offer_user_toggle"], + "gold_offer_user_toggle": values["gold_offer_user_toggle"], "1v1_battle_user_toggle": values["1v1_user_toggle"], "2v2_battle_user_toggle": values["2v2_user_toggle"], "upgrade_user_toggle": values["card_upgrade_user_toggle"], @@ -68,13 +77,12 @@ def make_job_dictionary(values: dict[str, str | int]) -> dict[str, str | int]: "skip_fight_if_full_chests_user_toggle" ], "disable_win_track_toggle": values["disable_win_track_toggle"], + # job increments "card_upgrade_increment_user_input": values[ "card_upgrade_increment_user_input" ], - "free_offer_collection_increment_user_input": values[ - "free_offer_collection_increment_user_input" - ], + "shop_buy_increment_user_input": values["shop_buy_increment_user_input"], "request_increment_user_input": values["request_increment_user_input"], "donate_increment_user_input": values["donate_increment_user_input"], "card_mastery_collect_increment_user_input": values[ @@ -195,7 +203,7 @@ def show_invalid_job_increment_input_popup(key) -> None: # A dictionary mapping the job increment input keys to their corresponding job names. key_to_job_dict: dict[str, str] = { "card_upgrade_increment_user_input": "Card Upgrade Increment", - "free_offer_collection_increment_user_input": "Free Offer Collection Increment", + "shop_buy_increment_user_input": "Shop Purchase Increment", "request_increment_user_input": "Request Increment", "donate_increment_user_input": "Donate Increment", "card_mastery_collect_increment_user_input": "Card Mastery Collect Increment", diff --git a/src/pyclashbot/bot/buy_shop_offers.py b/src/pyclashbot/bot/buy_shop_offers.py new file mode 100644 index 000000000..8a0e652b0 --- /dev/null +++ b/src/pyclashbot/bot/buy_shop_offers.py @@ -0,0 +1,164 @@ +import time + +from pyclashbot.bot.nav import ( + check_if_on_clash_main_menu, + get_to_shop_page_from_clash_main, +) +from pyclashbot.detection.image_rec import ( + find_references, + get_first_location, + get_file_count, + make_reference_image_list, +) +from pyclashbot.memu.client import ( + screenshot, + click, + scroll_down_slowly_in_shop_page, +) + +from pyclashbot.utils.logger import Logger + + +def search_for_free_purchases(vm_index): + """method to find the free offer icon image in the shop pages""" + + folder_name = "free_offer_icon" + size = get_file_count(folder_name) + names = make_reference_image_list(size) + locations = find_references( + screenshot(vm_index), + folder_name, + names, + 0.9, + ) + coord = get_first_location(locations) + if coord is None: + return None + return [coord[1], coord[0]] + + +def buy_free_offer(vm_index): + coord = search_for_free_purchases(vm_index) + + if coord is None: + return False + + # click the location of the free offer icon + click(vm_index, coord[0], coord[1]) + + # click the second 'buy' button + click(vm_index, 200, 433) + + # click deadspace to close this offer + click(vm_index, 15, 200, clicks=10) + + +def search_for_gold_purchases(vm_index): + """method to find the offers for gold icon image in the shop pages""" + + folder_name = "offers_for_gold" + size = get_file_count(folder_name) + names = make_reference_image_list(size) + locations = find_references( + screenshot(vm_index), + folder_name, + names, + 0.9, + ) + coord = get_first_location(locations) + if coord is None: + return None + return [coord[1], coord[0]] + + +def buy_offers_from_this_shop_page(vm_index, gold_buy_toggle, free_offers_toggle): + coord = None + + if gold_buy_toggle: + coord = search_for_gold_purchases(vm_index) + + # if no gold purchases, find a free purchase + if coord is None and free_offers_toggle: + coord = search_for_free_purchases(vm_index) + + # if there are no purchases at this point, return False + if coord is None: + return False + + # click the location of the 'cards for gold' icon + click(vm_index, coord[0], coord[1]) + time.sleep(2) + + # click the second 'buy' button + click(vm_index, 200, 433) + click(vm_index, 204, 394) + time.sleep(2) + + # click deadspace to close this offer + click(vm_index, 15, 200, clicks=10) + time.sleep(1) + return True + + +def buy_shop_offers_state( + vm_index: int, + logger: Logger, + gold_buy_toggle: bool, + free_offers_toggle: bool, + next_state: str, +): + print("Entering buy_shop_offers_state()") + print(f"gold_buy_toggle: {gold_buy_toggle}") + print(f"free_offers_toggle: {free_offers_toggle}") + + logger.add_shop_buy_attempt() + + # if not on clash main, return False + if not check_if_on_clash_main_menu(vm_index): + logger.change_status( + "Not on clash main to being buying offers. Returning restart" + ) + return "restart" + + # get to shop page + logger.change_status("Getting to shop page to buy offers") + if get_to_shop_page_from_clash_main(vm_index, logger) is False: + logger.change_status("Failed to get to shop page to buy offers") + return "restart" + + # scroll incrementally while searching for rewards, clicking and buying any rewards found + start_time = time.time() + timeout = 90 + logger.change_status("Starting to buy offers") + while 1: + if time.time() - start_time > timeout: + break + + # scroll a little + scroll_down_slowly_in_shop_page(vm_index) + time.sleep(0.33) + + if gold_buy_toggle: + while ( + buy_offers_from_this_shop_page( + vm_index, gold_buy_toggle, free_offers_toggle + ) + is True + ): + logger.change_status("Bought an offer from the shop!") + logger.add_shop_buy() + + # get to clash main from shop page + click(vm_index, 245, 596) + time.sleep(4) + + # if not on clash main, return False + if not check_if_on_clash_main_menu(vm_index): + logger.change_status("Not on clash main after buying offers. Returning restart") + return "restart" + + return next_state + + +if __name__ == "__main__": + pass diff --git a/src/pyclashbot/bot/free_offer_state.py b/src/pyclashbot/bot/free_offer_state.py deleted file mode 100644 index d8ec05049..000000000 --- a/src/pyclashbot/bot/free_offer_state.py +++ /dev/null @@ -1,195 +0,0 @@ -"""time module for timing methods and for sleeping while interacting with client""" -import time -from typing import Literal - -from pyclashbot.bot.nav import ( - check_if_on_clash_main_menu, - wait_for_clash_main_menu, - wait_for_clash_main_shop_page, -) -from pyclashbot.detection.image_rec import ( - check_line_for_color, - find_references, - get_file_count, - get_first_location, - make_reference_image_list, - region_is_color, -) -from pyclashbot.memu.client import ( - click, - screenshot, - scroll_down_fast_on_left_side_of_screen, -) -from pyclashbot.utils.logger import Logger - -SHOP_PAGE_BUTTON: tuple[Literal[33], Literal[603]] = (33, 603) -CLASH_MAIN_ICON_FROM_SHOP_PAGE: tuple[Literal[243], Literal[603]] = (243, 603) -FREE_BUTTON: tuple[Literal[216], Literal[425]] = (216, 425) -FREE_BUTTON_CONDITION_1_COORD: tuple[Literal[207], Literal[398]] = (207, 398) - -GREEN_COLOR: tuple[Literal[137], Literal[242], Literal[178]] = (137, 242, 178) - -FREE_OFFER_SCROLL_TIMEOUT = 35 # seconds - - -def get_to_shop_page(vm_index, logger): - click(vm_index, SHOP_PAGE_BUTTON[0], SHOP_PAGE_BUTTON[1]) - if wait_for_clash_main_shop_page(vm_index, logger) == "restart": - logger.change_status( - status="Error 085708235 Failure waiting for clash main shop page " - ) - return False - return True - - -def free_offer_collection_state(vm_index, logger: Logger, next_state: str) -> str: - """method to handle the entirety of the free offer collection state in the state tree""" - logger.set_current_state("free_offer_collection") - logger.change_status(status="Free offer collection state") - logger.add_free_offer_collection_attempt() - - clash_main_check = check_if_on_clash_main_menu(vm_index) - if clash_main_check is not True: - logger.change_status( - status="ERROR 356 Not on clash main menu for free_offer_collection_state" - ) - logger.log( - f"There are the pixels the bot saw after failing to find clash main:" - ) - for pixel in clash_main_check: - logger.log(f" {pixel}") - - return "restart" - - # get to shop page - if get_to_shop_page(vm_index, logger) is False: - logger.change_status("Failed to get to shop page!") - return "restart" - - logger.change_status(status="Searching for free offer") - start_time: float = time.time() - while 1: - # if looped too much, return - time_taken: float = time.time() - start_time - if time_taken > FREE_OFFER_SCROLL_TIMEOUT: - logger.log(f"Scrolled longer than {FREE_OFFER_SCROLL_TIMEOUT}s so breaking") - break - - # look for free offer - if find_and_click_free_offer(vm_index, logger) == "fail": - continue - - if buy_this_free_offer(vm_index, logger) == "good": - break - - # return to clash main - click( - vm_index, CLASH_MAIN_ICON_FROM_SHOP_PAGE[0], CLASH_MAIN_ICON_FROM_SHOP_PAGE[1] - ) - if wait_for_clash_main_menu(vm_index, logger) == "restart": - logger.change_status( - status="Error 777724 Failure waiting for clash main after free offer collection loops" - ) - return "restart" - - time.sleep(3) - - return next_state - - -def find_and_click_free_offer(vm_index, logger: Logger) -> Literal["fail", "good"]: - """method to find the click the free offer - image that appears in the clash shop page""" - - # look for a free offer - free_offer_coord = find_free_offer_icon(vm_index) - - # if the coord doesn't exist, scroll again, and return - if free_offer_coord is None: - # scroll - scroll_down_fast_on_left_side_of_screen(vm_index) - time.sleep(1) - click(vm_index, 13, 250) - return "fail" - - # if the coord exists, click the offer - logger.change_status(status="Collecting an available free offer!") - logger.log("Clicking this free offer: " + str(free_offer_coord)) - click(vm_index, free_offer_coord[0], free_offer_coord[1]) - time.sleep(2) - return "good" - - -def buy_this_free_offer(vm_index, logger) -> Literal["good"]: - """method to click the free! button that appears after - first clicking a free offer on the clash shop page""" - # click the 'Free!' button - logger.log("Cliking the free! price button") - if check_for_free_button_condition_1(vm_index): - click( - vm_index, - FREE_BUTTON_CONDITION_1_COORD[0], - FREE_BUTTON_CONDITION_1_COORD[1], - ) - else: - click(vm_index, FREE_BUTTON[0], FREE_BUTTON[1]) - - time.sleep(2) - - # click deadspace for if its a chest - logger.log("Clicking deadspace if its a chest") - click(vm_index, 5, 344, clicks=15, interval=0.75) - time.sleep(1) - - return "good" - - -def check_for_free_button_condition_1(vm_index) -> bool: - """method to check if the free! button exists""" - - if not check_line_for_color( - vm_index=vm_index, x_1=186, y_1=389, x_2=187, y_2=407, color=(255, 255, 255) - ): - return False - if not check_line_for_color( - vm_index=vm_index, x_1=222, y_1=389, x_2=221, y_2=406, color=(255, 255, 255) - ): - return False - - if not region_is_color( - vm_index=vm_index, region=[236, 400, 9, 6], color=(56, 228, 72) - ): - return False - if not region_is_color( - vm_index=vm_index, region=[171, 398, 11, 10], color=(56, 228, 72) - ): - return False - - return True - - -def find_free_offer_icon(vm_index): - """method to find the free offer icon image in the shop pages""" - - folder_name = "free_offer_icon" - size = get_file_count(folder_name) - names = make_reference_image_list(size) - locations = find_references( - screenshot(vm_index), - folder_name, - names, - 0.9, - ) - coord = get_first_location(locations) - if coord is None: - return None - return [coord[1], coord[0]] - - -if __name__ == "__main__": - vm_index = 11 - logger = Logger() - - free_offer_collection_state(vm_index, logger, "next_state") - - # get_to_shop_page(vm_index, logger) diff --git a/src/pyclashbot/bot/level_up_chest.py b/src/pyclashbot/bot/level_up_chest.py index 6543b605b..49d232ad7 100644 --- a/src/pyclashbot/bot/level_up_chest.py +++ b/src/pyclashbot/bot/level_up_chest.py @@ -1,7 +1,8 @@ - import numpy +from pyclashbot.detection.image_rec import pixel_is_equal from pyclashbot.memu.client import screenshot + def check_for_level_up_chest(vm_index): iar = numpy.asarray(screenshot(vm_index)) @@ -12,16 +13,24 @@ def check_for_level_up_chest(vm_index): iar[23][16], ] - for i,p in enumerate(pixels): - print(p) + colors = [ + [245, 195, 79], + [246, 215, 63], + [108, 211, 247], + [221, 169, 39], + ] + for i, p in enumerate(pixels): + if not pixel_is_equal(p, colors[i], tol=15): + return True -def collect_bannerbox_chest(): + return False +def collect_bannerbox_chest(): pass -if __name__ == '__main__': - vm_index=11 - check_for_level_up_chest(vm_index) +if __name__ == "__main__": + vm_index = 12 + print(check_for_level_up_chest(vm_index)) diff --git a/src/pyclashbot/bot/nav.py b/src/pyclashbot/bot/nav.py index 52d446074..3ca6b053d 100644 --- a/src/pyclashbot/bot/nav.py +++ b/src/pyclashbot/bot/nav.py @@ -34,6 +34,19 @@ OPEN_WAR_CHEST_BUTTON_COORD = (188, 415) OPENING_WAR_CHEST_DEADZONE_COORD = (5, 298) CLASH_MAIN_WAIT_TIMEOUT = 240 # s +SHOP_PAGE_BUTTON: tuple[Literal[33], Literal[603]] = (33, 603) + + +def get_to_shop_page_from_clash_main(vm_index, logger): + click(vm_index, SHOP_PAGE_BUTTON[0], SHOP_PAGE_BUTTON[1]) + if wait_for_clash_main_shop_page(vm_index, logger) == "restart": + logger.change_status( + status="Error 085708235 Failure waiting for clash main shop page " + ) + return False + return True + + def wait_for_end_battle_screen( diff --git a/src/pyclashbot/bot/states.py b/src/pyclashbot/bot/states.py index ee3925617..499284e08 100644 --- a/src/pyclashbot/bot/states.py +++ b/src/pyclashbot/bot/states.py @@ -12,7 +12,6 @@ start_1v1_fight_state, start_2v2_fight_state, ) -from pyclashbot.bot.free_offer_state import free_offer_collection_state from pyclashbot.bot.nav import wait_for_clash_main_menu from pyclashbot.bot.open_chests_state import get_chest_statuses, open_chests_state from pyclashbot.bot.request_state import request_state @@ -23,6 +22,7 @@ restart_emulator, start_clash_royale, ) +from pyclashbot.bot.buy_shop_offers import buy_shop_offers_state from pyclashbot.utils.logger import Logger @@ -161,8 +161,8 @@ def state_tree( # return output of this state return request_state(vm_index, logger, next_state) - if state == "donate": # --> free_offer_collection - next_state = "free_offer_collection" + if state == "donate": # --> shop_buy + next_state = "shop_buy" # if job not selected, return next state if not job_list["donate_toggle"]: @@ -177,24 +177,30 @@ def state_tree( # return output of this state return donate_cards_state(vm_index, logger, next_state) - - if state == "free_offer_collection": # --> bannerbox + if state == "shop_buy": # --> bannerbox next_state = "bannerbox" # if job not selected, return next state - if not job_list["free_offer_user_toggle"]: - logger.log("Free offer state isn't toggled") + if ( + not job_list["free_offer_user_toggle"] + and not job_list["gold_offer_user_toggle"] + ): + logger.log("Free neither free, not gold offer buys toggled") return next_state # if job not ready, reutrn next state - if not logger.check_if_can_collect_free_offer( - job_list["free_offer_collection_increment_user_input"] - ): - logger.log("Free offer state isn't ready") + if not logger.check_if_can_shop_buy(job_list["shop_buy_increment_user_input"]): + logger.log("Free shop_buy isn't ready") return next_state # return output of this state - return free_offer_collection_state(vm_index, logger, next_state) + return buy_shop_offers_state( + vm_index, + logger, + job_list["gold_offer_user_toggle"], + job_list["free_offer_user_toggle"], + next_state, + ) if state == "bannerbox": # --> randomize_deck next_state = "randomize_deck" @@ -345,9 +351,7 @@ def state_tree( return next_state account_total = job_list["account_switching_slider"] - logger.log( - f"Doing switch to act#{job_list['next_account']} of {account_total}" - ) + logger.log(f"Doing switch to act#{job_list['next_account']} of {account_total}") if switch_accounts(vm_index, logger, job_list["next_account"]) is False: return "restart" diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/1.png b/src/pyclashbot/detection/reference_images/offers_for_gold/1.png new file mode 100644 index 000000000..35954481c Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/1.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/10.png b/src/pyclashbot/detection/reference_images/offers_for_gold/10.png new file mode 100644 index 000000000..dd109b275 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/10.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/11.png b/src/pyclashbot/detection/reference_images/offers_for_gold/11.png new file mode 100644 index 000000000..cb9d4082e Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/11.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/12.png b/src/pyclashbot/detection/reference_images/offers_for_gold/12.png new file mode 100644 index 000000000..a4698d682 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/12.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/13.png b/src/pyclashbot/detection/reference_images/offers_for_gold/13.png new file mode 100644 index 000000000..d884652b4 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/13.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/14.png b/src/pyclashbot/detection/reference_images/offers_for_gold/14.png new file mode 100644 index 000000000..57ba3d7f2 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/14.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/15.png b/src/pyclashbot/detection/reference_images/offers_for_gold/15.png new file mode 100644 index 000000000..c6b36a7b9 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/15.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/16.png b/src/pyclashbot/detection/reference_images/offers_for_gold/16.png new file mode 100644 index 000000000..dfa0ae96a Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/16.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/17.png b/src/pyclashbot/detection/reference_images/offers_for_gold/17.png new file mode 100644 index 000000000..9e0529013 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/17.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/18.png b/src/pyclashbot/detection/reference_images/offers_for_gold/18.png new file mode 100644 index 000000000..0807bcc48 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/18.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/19.png b/src/pyclashbot/detection/reference_images/offers_for_gold/19.png new file mode 100644 index 000000000..cc079c2da Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/19.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/2.png b/src/pyclashbot/detection/reference_images/offers_for_gold/2.png new file mode 100644 index 000000000..b0be17724 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/2.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/3.png b/src/pyclashbot/detection/reference_images/offers_for_gold/3.png new file mode 100644 index 000000000..fb8d0e6c3 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/3.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/4.png b/src/pyclashbot/detection/reference_images/offers_for_gold/4.png new file mode 100644 index 000000000..dcbb46149 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/4.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/5.png b/src/pyclashbot/detection/reference_images/offers_for_gold/5.png new file mode 100644 index 000000000..042b88ddf Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/5.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/6.png b/src/pyclashbot/detection/reference_images/offers_for_gold/6.png new file mode 100644 index 000000000..5be1f951a Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/6.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/7.png b/src/pyclashbot/detection/reference_images/offers_for_gold/7.png new file mode 100644 index 000000000..9337116b1 Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/7.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/8.png b/src/pyclashbot/detection/reference_images/offers_for_gold/8.png new file mode 100644 index 000000000..1c85ea57d Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/8.png differ diff --git a/src/pyclashbot/detection/reference_images/offers_for_gold/9.png b/src/pyclashbot/detection/reference_images/offers_for_gold/9.png new file mode 100644 index 000000000..7df5ca87f Binary files /dev/null and b/src/pyclashbot/detection/reference_images/offers_for_gold/9.png differ diff --git a/src/pyclashbot/interface/controls.py b/src/pyclashbot/interface/controls.py index 50ef11498..13b69a996 100644 --- a/src/pyclashbot/interface/controls.py +++ b/src/pyclashbot/interface/controls.py @@ -46,7 +46,7 @@ def make_job_increment_control_object(key): [make_job_increment_control_object("donate_increment_user_input")], [ make_job_increment_control_object( - "free_offer_collection_increment_user_input" + "shop_buy_increment_user_input" ) ], [ diff --git a/src/pyclashbot/interface/joblist.py b/src/pyclashbot/interface/joblist.py index e602ba745..ee5b42762 100644 --- a/src/pyclashbot/interface/joblist.py +++ b/src/pyclashbot/interface/joblist.py @@ -75,10 +75,16 @@ def job_check_box(text: str, element_key: str, default_value=True) -> sg.Checkbo ], [ job_check_box( - "Free Offer Collection", + "Free Offers Collection", "free_offer_user_toggle", ), ], + [ + job_check_box( + "Gold Offers Collection", + "gold_offer_user_toggle", + ), + ], [ job_check_box( "Disable win/loss tracking", diff --git a/src/pyclashbot/interface/layout.py b/src/pyclashbot/interface/layout.py index e872bd257..254444726 100644 --- a/src/pyclashbot/interface/layout.py +++ b/src/pyclashbot/interface/layout.py @@ -196,6 +196,7 @@ def get_random_donate_image_path(): "card_mastery_user_toggle", 'disable_win_track_toggle', "free_offer_user_toggle", + "gold_offer_user_toggle", "1v1_user_toggle", "2v2_user_toggle", "card_upgrade_user_toggle", @@ -207,7 +208,7 @@ def get_random_donate_image_path(): # job increment controls keys "request_increment_user_input", "donate_increment_user_input", - "free_offer_collection_increment_user_input", + "shop_buy_increment_user_input", "card_upgrade_increment_user_input", "card_mastery_collect_increment_user_input", "open_chests_increment_user_input", diff --git a/src/pyclashbot/interface/stats.py b/src/pyclashbot/interface/stats.py index f382009a0..9384d914c 100644 --- a/src/pyclashbot/interface/stats.py +++ b/src/pyclashbot/interface/stats.py @@ -23,6 +23,9 @@ def stat_box(stat_name: str, size=(5, 1)) -> sg.Text: [ sg.Text("Requests: "), ], + [ + sg.Text("Shop Buys: "), + ], [ sg.Text("Donates: "), ], @@ -44,6 +47,9 @@ def stat_box(stat_name: str, size=(5, 1)) -> sg.Text: [ stat_box("requests"), ], + [ + stat_box("shop_buys"), + ], [ stat_box("donates"), ], diff --git a/src/pyclashbot/memu/client.py b/src/pyclashbot/memu/client.py index 081bd4cab..f4922fdd6 100644 --- a/src/pyclashbot/memu/client.py +++ b/src/pyclashbot/memu/client.py @@ -58,6 +58,9 @@ def scroll_up_on_left_side_of_screen(vm_index): send_swipe(vm_index, 66, 300, 66, 400) + + + def scroll_down(vm_index): """Method for scrolling down faster when interacting with a scrollable menu""" send_swipe(vm_index, 215, 400, 215, 300) @@ -69,6 +72,14 @@ def scroll_down_fast_on_left_side_of_screen(vm_index): send_swipe(vm_index, 66, 400, 66, 300) +def scroll_down_slowly_in_shop_page(vm_index): + """Method for scrolling down even faster when interacting with a + scrollable menu using the left side of the screen""" + send_swipe(vm_index, 66, 400, 66, 300) + + #click deadspace to stop the scroll + click(vm_index,10,200) + def send_swipe( vm_index: int, x_coord1: int, y_coord1: int, x_coord2: int, y_coord2: int ): diff --git a/src/pyclashbot/memu/launcher.py b/src/pyclashbot/memu/launcher.py index d077294b9..dd2be22a6 100644 --- a/src/pyclashbot/memu/launcher.py +++ b/src/pyclashbot/memu/launcher.py @@ -88,7 +88,6 @@ def skip_ads(vm_index): time.sleep(1) except Exception as err: # pylint: disable=broad-except print(f"Fail sending home clicks to skip ads... Redoing restart...\n{err}") - input("Enter to cont") return "fail" return "success" diff --git a/src/pyclashbot/memu/screenshot.py b/src/pyclashbot/memu/screenshot.py index 7aa9118d3..d49c86891 100644 --- a/src/pyclashbot/memu/screenshot.py +++ b/src/pyclashbot/memu/screenshot.py @@ -2,7 +2,7 @@ A module for getting screenshots from Memu VMs. """ import atexit - +import time import numpy as np from adbblitz import AdbShotTCP @@ -26,12 +26,15 @@ def __init__(self): def __getitem__(self, vm_index: int) -> np.ndarray: if vm_index not in self.connections: - host, port = pmc.get_adb_connection(vm_index=vm_index) + # host, port = pmc.get_adb_connection(vm_index=vm_index) + outputs = pmc.get_adb_connection(vm_index=vm_index) + host,port = outputs self.connections[vm_index] = AdbShotTCP( device_serial=f"{host}:{port}", adb_path=adb_path, log_level="ERROR", ) + time.sleep(0.01) return np.array(self.connections[vm_index].get_one_screenshot()) def __del__(self): diff --git a/src/pyclashbot/utils/logger.py b/src/pyclashbot/utils/logger.py index 130201f6e..28b82139e 100644 --- a/src/pyclashbot/utils/logger.py +++ b/src/pyclashbot/utils/logger.py @@ -100,6 +100,7 @@ def __init__( # job stats self.requests = 0 + self.shop_buys = 0 self.donates = 0 self.request_attempts = 0 self.donate_attempts = 0 @@ -109,7 +110,7 @@ def __init__( self.card_upgrade_attempts = 0 self.card_mastery_reward_collections = 0 self.free_offer_collections = 0 - self.free_offer_collection_attempts = 0 + self.shop_buy_attempts = 0 self.chest_unlock_attempts = 0 self.card_mastery_reward_collection_attempts = 0 self.war_attempts = 0 @@ -150,6 +151,7 @@ def _update_stats(self) -> None: "2v2_fights": self._2v2_fights, "upgrades": self.cards_upgraded, "requests": self.requests, + "shop_buys": self.shop_buys, 'donates': self.donates, "restarts_after_failure": self.restarts_after_failure, "chests_unlocked": self.chests_unlocked, @@ -326,6 +328,12 @@ def add_request(self) -> None: """add request to log""" self.requests += 1 + @_updates_log + def add_shop_buy(self) -> None: + """add request to log""" + self.shop_buys += 1 + + @_updates_log def add_donate(self) -> None: """add donate to log""" @@ -371,10 +379,9 @@ def add_request_attempt(self): def add_donate_attempt(self): self.donate_attempts += 1 - - def add_free_offer_collection_attempt(self): + def add_shop_buy_attempt(self): """increments logger's free_offer_collection_attempts by 1""" - self.free_offer_collection_attempts += 1 + self.shop_buy_attempts += 1 def add_card_upgrade_attempt(self): """increments logger's card_upgrade_attempts by 1""" @@ -653,7 +660,7 @@ def check_if_can_donate(self, increment) -> bool: self.log(f"Can't donate. {games_played} games and {donate_attempts} Attempts") return False - def check_if_can_collect_free_offer(self, increment) -> bool: + def check_if_can_shop_buy(self, increment) -> bool: """method to check if can collect free offers given attempts, games played, and user increment input""" @@ -662,35 +669,35 @@ def check_if_can_collect_free_offer(self, increment) -> bool: self.log(f"Increment is {increment} so can always Collect Free Offers") return True - # count free_offer_collection_attempts - free_offer_attempts = self.free_offer_collection_attempts + # count shop_buy_attempts + shop_buy_attempts = self.shop_buy_attempts # count games games_played = self._1v1_fights + self._2v2_fights + self.war_fights - # if free_offer_collection_attempts is zero return true - if free_offer_attempts == 0: + # if shop_buy_attempts is zero return true + if shop_buy_attempts == 0: self.log( - f"Can collect free offer. {games_played} Games and {free_offer_attempts} Attempts" + f"Can collect shop_buy. {games_played} Games and {shop_buy_attempts} Attempts" ) return True # if games_played is zero return true if games_played == 0: self.log( - f"Can collect free offer. {games_played} Games and {free_offer_attempts} Attempts" + f"Can collect shop_buy. {games_played} Games and {shop_buy_attempts} Attempts" ) return True - # if games_played / increment > free_offer_collection_attempts - if games_played / increment >= free_offer_attempts: + # if games_played / increment > shop_buy_attempts + if games_played / increment >= shop_buy_attempts: self.log( - f"Can collect free offer. {games_played} Games and {free_offer_attempts} Attempts" + f"Can collect shop_buy. {games_played} Games and {shop_buy_attempts} Attempts" ) return True self.log( - f"Can't do free offer. {games_played} Games and {free_offer_attempts} Attempts" + f"Can't do shop_buy . {games_played} Games and {shop_buy_attempts} Attempts" ) return False