def navigate_to_cancel_button(context): for _ in range(3): press(context, keys.KEY_DOWN, 1) if check_cancel_button_visible(context): return AssertionError("Failed to navigate to cancel button.")
def enter_string(context, title, move_to_search_result=True): """ TODO: need to add code to handle special chars. Takes a string and uses soft keyboard to input the title After entering the string, move the highlight to bottom right corner of the keyboard. :param title: (str) content title :param move_to_search_result: (bool) if True, move to search result, otherwise move to suggestions :return: (int, int) coordinate of last character at input string """ print("\n === Search title: [{}] ====\n\n".format(title)) # Start from row 1 and col 0 to skip first row which only has two keys. # We can directly move to (0, 0) to locate "ABC / 123" key, # or directly move to (0, 0), then press KEY_RIGHT to locate "#!@" key current_coordinate = [1, 0] for c in title: if c == " ": c = KBD_SPACE print("========= Character ", c) next_coordinate = find_keyboard_mapping(search_kb_layout, c) move_to_char_pos_keyboard(context, current_coordinate[0], current_coordinate[1], next_coordinate[0], next_coordinate[1]) current_coordinate = next_coordinate press(context, keys.KEY_SELECT, delay=1) print("=== OK pressed ===") print(f"current_coordinate is: {current_coordinate}") context.current_coordinate = current_coordinate
def step_impl(context, no): assert navigate_to( context, "chapter", focus_threshold=30), "fail to find chapter on progress bar" # navigate to the dest. chapter found_chapter = find_current_chapters(context) assert found_chapter > 0, "no focused chapter found" cur_row = (found_chapter - 1) // CHAPTER_GRID_COLS cur_col = (found_chapter - 1) % CHAPTER_GRID_COLS debug(f"cur row:{cur_row}, cur col:{cur_col}") dest_row = (int(no) - 1) // CHAPTER_GRID_COLS dest_col = (int(no) - 1) % CHAPTER_GRID_COLS debug(f"dest row:{dest_row}, dest col:{dest_col}") for _ in range(abs(dest_col - cur_col)): if dest_col > cur_col: press(context, keys.KEY_RIGHT, 1) elif dest_col < cur_col: press(context, keys.KEY_RIGHT, 1) for _ in range(abs(dest_row - cur_row)): if dest_row > cur_row: press(context, keys.KEY_DOWN, 1) elif dest_row < cur_row: press(context, keys.KEY_UP, 1) press(context, keys.KEY_SELECT)
def step_impl(context): press(context, keys.KEY_DOWN, 1) # to show progress bar cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(context.frame) frame = cv2.imread(context.frame) mp = (0, 0.8, *get_default_match_parameter()[2::] ) # use ccorr_normed method 0 and threshold =0.65 video_quality = "None" result = 0.0 assert os.path.exists(playback_soft_buttons["play off unhilitefamily"][1]) found = match(frame, cv2.imread( playback_soft_buttons['family play off unhilite'][1]), REGION_PROGRESS_BAR, match_parameter=mp) if found[0] is True: debug(f"found family play off\n") return assert os.path.exists(playback_soft_buttons["family play on unhilite"][1]) found = match(frame, cv2.imread( playback_soft_buttons['family play on unhilite'][1]), REGION_PROGRESS_BAR, match_parameter=mp) if found[0] is True: debug(f"found family play on\n") return debug(f"fail to find family play on the progress barn\n") assert False, "fail to find family play on the progress bar"
def step_impl(context): # read ads watch time and program time cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") start = time.time() success = 0 while True and time.time() < start + 180: press(context, keys.KEY_DOWN) # to show progress bar assert 200 == cam.get_frame(context.frame) region = Region(x=900, y=640, right=1110, bottom=720) ads = ocr(cv2.imread(context.frame), region, grayscale=True, invert_grayscale=True) debug(f"ads: {ads}") region = Region(x=1110, y=640, right=1280, bottom=720) counter = ocr(cv2.imread(context.frame), region, grayscale=True, invert_grayscale=True) debug(f"counter: {counter}") debug(f"ads/counter: {ads} / {counter}\n") if "Ad" not in ads and ":" not in counter: success += 1 if success > 3: return assert False, "ads is still playing"
def step_impl(context, screen): assert screen in MENU_SCREEN_TABS, f"error: unknown {screen} tab on the menu page" if screen == MENU_SCREEN_TABS[0]: key = keys.KEY_LEFT max_try = 2 else: max_try = len(MENU_SCREEN_TABS) - 1 key = keys.KEY_RIGHT goto_vudu_home(context) # we are in menu screen now # check current selection is on spotlight cam = context.cam while max_try: context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(path=context.frame) text_in_highlight, region = find_selection_text( cv2.imread(context.frame), cv2.imread(MAIN_MENU_SEL_LEFT), cv2.imread(MAIN_MENU_SEL_RIGHT), x_offset=10, y_offset=5, region=Region(0, 0, 1000, 80), match_parameter=get_default_match_parameter()) debug(f"current selection is {text_in_highlight} at {region}") if text_in_highlight is not None and screen.lower( ) in text_in_highlight.lower(): debug(f"found {screen}") return press(context, key, 1) max_try -= 1 assert False, f"fail to go to {screen} tab on the menu page"
def move_to_search_suggestions(context): """ Navigate down to the first search suggestions result :param col_location: (int) current col position. """ print(f"current_coordinate is: {context.current_coordinate}") move_loop_count = search_kb_row_total - context.current_coordinate[0] print("move_loop_count: {}".format(move_loop_count)) for no in range(move_loop_count): print(f"\n\n === Count to move right {no}") press(context, keys.KEY_DOWN, delay=1)
def move_to_search_result(context): """ Navigate to the first poster in search result in right side. :param r_location: (int) current row position. """ print("---- Navigate right to the first poster.") move_loop_count = search_kb_col_total - context.current_coordinate[1] print("move_loop_count: {}".format(move_loop_count)) for no in range(move_loop_count): print("\n\n === Count to move right {}".format(no)) press(context, keys.KEY_RIGHT, delay=1)
def select_rent_button(context, quality=consts.QUALITY_HDX): """ Arrow right to move to Rent button. The button orders are: Rent -> Own -> Disc :return: new page """ if is_single_purchase_price_rent_visible(context): navigate_to_single_price_grid_rent(context, quality) else: navigate_to_rent_own_button(context, quality) press(context, keys.KEY_SELECT, 3)
def step_impl(context): # check if we are on mai menu ? if not use home key to return home page. # if soptlight selection not on focus, restart Vudu press(context, keys.KEY_BACK) press(context, keys.KEY_REWIND) set_default_match_paramter(MATCH_PARAMETER) current_menu_sel_text = current_menu_selection(context) if current_menu_sel_text is not None and "spotlight" in current_menu_sel_text.lower( ): return launch_vudu(context)
def step_impl(context, settings_tab): assert settings_tab in SETTINGS_PAGE_TABS, f"{settings_tab} is an unknown button" press(context, key=keys.KEY_SELECT) result = search_by_text_from_ext_capture( context, region=REGION_SETTINGS_TABS, left_bk=cv2.imread(SETTINGS_MENU_SEL), right_bk=None, target=settings_tab, key_to_press=keys.KEY_DOWN, max_tries=len(SETTINGS_PAGE_TABS)) assert result, f"{settings_tab} is not found/selected" press(context, key=keys.KEY_SELECT)
def step_impl(context, button): assert button in DETAIL_PAGE_BUTTONS, f"{button} is an unknown button" result = search_by_text_from_ext_capture( context, region=REGION_DETAIL_BUTTONS, left_bk=cv2.imread(DETAIL_TAB_SEL), right_bk=None, target=button, key_to_press=keys.KEY_DOWN, max_tries=len(DETAIL_PAGE_BUTTONS)) assert result, f"{button} is not found/selected" context.movie_title = title(context) press(context, key=keys.KEY_SELECT)
def navigate_to(context, button, focus_threshold=None): assert button in playback_soft_buttons press(context, keys.KEY_DOWN, 1) # to show progress bar key_to_press = playback_soft_buttons[button][0] mp = (3, 0.65, *get_default_match_parameter()[2::] ) # use fixed method 3 and threshold =0.65 return search_by_image(context, REGION_PROGRESS_BAR, playback_soft_buttons[button][1], key_to_press, max_tries=7, mp=mp, hist=SEARCH_BY_IMAGE_USE_BRIGHTNESS, focus_threshold=focus_threshold)
def navigate_to_single_price_grid_buy(context, quality=consts.QUALITY_HDX): # new single price pop up cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(path=context.frame) frame = cv2.imread(context.frame) assert is_single_purchase_price_buy_visible(context, frame), "Single price buy is not visible." if is_single_purchase_price_un_focus_buy_visible(context,frame): press(context, keys.KEY_RIGHT, 1) print(f"Move to {quality}") price_selection = current_price_grid_selection(context) print(f"The selected price option is: {price_selection}") if quality == consts.QUALITY_ANY: return if quality == consts.QUALITY_HDX: if price_4k in price_selection: press(context, keys.KEY_DOWN, 1) price_selection = current_price_grid_selection(context) print(f"HDX: The selected price option is: {price_selection}") if consts.QUALITY_HDX in price_selection: return True elif quality == consts.QUALITY_SD: press(context, keys.KEY_DOWN, 1) press(context, keys.KEY_DOWN, 1) return True else: if price_4k in price_selection: return True assert False, f"Failed to navigate to rent {quality} option"
def check_orange_price_tag(self): # check orange price on purchase pop up page. if self.check_discount_price(): print("Find orange price tag") return True else: # This is the case, the current select is the only once price. Move to cancel button so that we can check # the price print("Need to navigate to Cancel button first to check orange price tag.") self.navigate_to_cancel_button() if self.check_discount_price(): print("Need to move up back") press(context, keys.KEY_DOWN, 1) press(context, keys.KEY_UP) return True return False
def step_impl(context): # read watch time and program time press(context, keys.KEY_DOWN) cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(context.frame) counter = ocr(cv2.imread(context.frame), REGION_PROGRESS_BAR_TIME, grayscale=True, invert_grayscale=True, ocr_parameter='-c tessedit_char_whitelist=0123456789/:') debug(f"counter: {counter}\n") assert "/" in counter, "no counter found" play_time, program_time = parse_play_time_and_program_time(counter) debug(f"play time / program time: {play_time}/{program_time}") context.play_time = play_time context.program_time = program_time
def find_current_chapters(context): press(context, keys.KEY_SELECT, 1) # to show chapter grid cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(context.frame) frame = cv2.imread(context.frame) mp = (3, 0.8, *get_default_match_parameter()[2::] ) # use ccorr_normed method 0 and threshold =0.65 debug(f"match {playback_chapter['chapter']}") result = match(frame, cv2.imread(playback_chapter["chapter"]), REGION_CHAPTER_GRID, match_parameter=mp) print("\n\n") assert result[0] is True, f"fail to find current chapter" # find current chapter chapter_grids_width = REGION_CHAPTER_GRID.right - REGION_CHAPTER_GRID.x chapter_grids_height = REGION_CHAPTER_GRID.bottom - REGION_CHAPTER_GRID.top chapter_width = chapter_grids_width // CHAPTER_GRID_COLS chapter_height = chapter_grids_height // CHAPTER_GRID_ROWS chapters_regions = [] for row in range(CHAPTER_GRID_ROWS): for col in range(CHAPTER_GRID_COLS): chapters_regions.append( Region(REGION_CHAPTER_GRID.x + col * chapter_width, REGION_CHAPTER_GRID.y + row * chapter_height, REGION_CHAPTER_GRID.x + (col + 1) * chapter_width, REGION_CHAPTER_GRID.y + (row + 1) * chapter_height)) # debug(f"chapter: {len(chapters_regions) + 1}, {chapters_regions[-1]}") found_chapters = [] focused_chapter = 0 focused_chapter_area = 0 for chp in range(len(chapters_regions)): area = Region.intersect_area(result[1], chapters_regions[chp]) # debug(f"intersect area {result[1]} and {chapters_regions[chp]}, area: {area}") if area > 0: found_chapters.append((chp, area)) debug(f"chapter {chp + 1}, area: {area}") if area > focused_chapter_area: focused_chapter = chp + 1 focused_chapter_area = area return focused_chapter
def step_impl(context, result): cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") move_to_search_result(context) for count in range(3): # search_region = regions.REGION_SIDE_PANEL_DICT[consts.SEARCH] assert 200 == cam.get_frame(context.frame) frame = cv2.imread(context.frame) read_title = ocr(region=REGION_SEARCH_TITLE, frame=frame).replace('\n', " ").upper() debug("=== Read out text: {}".format(read_title)) if result in read_title: debug(f"Find result: {result}") return result else: debug(f"Didn't find the expected {result}. Move to next poster: ") press(context, keys.KEY_RIGHT, delay=2) assert False, f"Didn't find the expected {result}."
def select_own_button(context, quality=consts.QUALITY_HDX): """ Arrow right to move to Own button. The button orders are: Rent -> Own -> Disc :quality: (str) HDX or SD :return: new page """ if is_single_purchase_price_buy_visible(context): print("Info: Single price grid is enabled.") navigate_to_single_price_grid_buy(context, quality) else: print("Info: This is old price grid") press(context, keys.KEY_RIGHT) # TBD: fix the case there is no rent but buy and D+D options assert (quality in consts.QUALITY) current_quality = get_current_rental_quality(context) print(f"current quality: {current_quality}, dest quality: {quality}") navigate_to_rent_own_button(context, quality) print(f"=== Press [OK] to select own quality: {quality}") press (context, keys.KEY_SELECT, 3)
def step_impl(context, switch): press(context, keys.KEY_DOWN, 1) # to show progress bar cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(context.frame) frame = cv2.imread(context.frame) mp = (3, 0.7, *get_default_match_parameter()[2::] ) # use ccorr_normed method 0 and threshold =0.65 debug("check current switch\n") if switch == "off": debug(f"match {playback_soft_buttons['family play off unhilite'][1]}") if match(frame, cv2.imread( playback_soft_buttons["family play off unhilite"][1]), REGION_PROGRESS_BAR, match_parameter=mp)[0] is True: debug(f"family play is already {switch}\n") return elif switch == "on": debug(f"match {playback_soft_buttons['family play on unhilite'][1]}") if match(frame, cv2.imread( playback_soft_buttons["family play on unhilite"][1]), REGION_PROGRESS_BAR, match_parameter=mp)[0] is True: debug(f"family play is already {switch}\n") return debug(f"navigate_to family play {switch}\n") if navigate_to(context, "family play on" if switch == "off" else "family play off"): press(context, keys.KEY_SELECT, 1) # press(context, keys.KEY_UP, 1) press(context, keys.KEY_SELECT, 1) # dismiss family play popup press(context, keys.KEY_SELECT, 1) if switch == "on": press(context, keys.KEY_SELECT, 1) # dismiss family play popup return
def step_impl(context, switch): assert switch == "on" or switch == "off" press(context, keys.KEY_DOWN, 1) # to show progress bar cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(context.frame) region = REGION_PROGRESS_BAR frame = cv2.imread(context.frame) mp = (3, 0.8, *get_default_match_parameter()[2::] ) # use ccorr_normed method 0 and threshold =0.65 if switch == "off": debug(f"match {playback_soft_buttons['cc off unhilite'][1]}") if match(frame, cv2.imread(playback_soft_buttons["cc off unhilite"][1]), region, match_parameter=mp)[0] is True: debug(f"closed caption is already {switch}\n\n") return elif switch == 'on': debug(f"match {playback_soft_buttons['cc on unhilite'][1]}") if match(frame, cv2.imread(playback_soft_buttons["cc on unhilite"][1]), region, match_parameter=mp)[0] is True: debug(f"closed caption is already {switch}") return debug(f"navigate_to {switch}\n\n") if navigate_to(context, "cc on" if switch == "off" else "cc off"): press(context, keys.KEY_SELECT, 1) # press(context, keys.KEY_UP, 1) press(context, keys.KEY_SELECT, 1) return assert False, f"fail to switch {switch} closed caption"
def step_impl(context, no): row = (int(no) - 1) // 5 col = int(no) - row * 5 - 1 for _ in range(row): press(context, keys.KEY_DOWN) for _ in range(col): press(context, keys.KEY_RIGHT) press(context, keys.KEY_SELECT)
def step_impl(context): # read ads watch time and program time press(context, keys.KEY_DOWN) cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") assert 200 == cam.get_frame(context.frame) shoppable_ads_detected = False if detect_shoppable_ads is True: shoppable_ads_detected = detect_shoppable_ads() else: shoppable_ads_detected = False region = Region(x=950, y=640, right=1110, bottom=720) ads = ocr(cv2.imread(context.frame), region, grayscale=True, invert_grayscale=True) debug(f"ads: {ads}") region = Region(x=1110, y=640, right=1280, bottom=720) counter = ocr(cv2.imread(context.frame), region, grayscale=True, invert_grayscale=True) debug(f"counter: {counter}") debug(f"ads/counter: {ads} / {counter}\n") assert "Ad" in ads or ":" in counter, "no ads found" current_ads, total_ads, ads_min, ads_sec = parse_ads_and_counter( ads, counter) if detect_shoppable_ads is True and shoppable_ads_detected is False: assert 200 == cam.get_frame(context.frame) shoppable_ads_detected = detect_shoppable_ads() debug( f"current_ads:{current_ads}, total_ads:{total_ads}, ads_min:{ads_min}, ads_sec:{ads_sec}, shoppable_ads_detected:{shoppable_ads_detected}" )
def step_impl(context, result): cam = context.cam context.frame = get_frame_name(context, f"{WORK_DIR}/_frame.png") move_to_search_suggestions(context) debug("\n\n=== Read search suggestion.") mp = (3, 0.65, *get_default_match_parameter()[2::]) # use fixed method 3 and threshold =0.65 for _ in range(3): assert 200 == cam.get_frame(context.frame) frame = cv2.imread(context.frame) text_read_out, region = find_selection_text(cv2.imread(context.frame), cv2.imread(SEARCH_SUGGESTION_SEL_LEFT), cv2.imread(SEARCH_SUGGESTION_SEL_RIGHT), region=REGION_SEARCH_SUGGESTIONS, match_parameter=mp) format_read_out = text_read_out.upper() debug(f"The formatted read out: {format_read_out}") if result in format_read_out: debug("Find expected search string in search suggestion") return press(context, keys.KEY_DOWN, delay=1) time.sleep(2) raise AssertionError(f"Failed to find {result} in search menu")
def step_impl(context): press(context, keys.KEY_DOWN) # submenu press(context, keys.KEY_DOWN)
def step_impl(context): # press(context, keys.KEY_RIGHT) press(context, keys.KEY_SELECT)
def step_impl(context): press(context, keys.KEY_SELECT)
def step_impl(context): press(context, keys.KEY_DOWN, 1) # submenu press(context, keys.KEY_DOWN, 1) # Promo press(context, keys.KEY_DOWN, 1) # Browse All Free Titles press(context, keys.KEY_DOWN, 1) # New This Month
def step_impl(context, button): if button == "ok": press(context, keys.KEY_SELECT, 3) else: press(context, keys.KEY_RIGHT, 3) press(context, keys.KEY_SELECT, 3)
def step_impl(context): press(context, keys.KEY_DOWN, 1) press(context, keys.KEY_SELECT, 3)