Added benchmark

This commit is contained in:
Lukas Wölfer
2020-02-12 02:04:50 +01:00
parent a624a06f82
commit c05aa194ce
6 changed files with 178 additions and 126 deletions

View File

@@ -0,0 +1,123 @@
import time
from typing import List, Tuple
import pyautogui
import shenzhen_solitaire.board as board
import shenzhen_solitaire.card_detection.adjustment as adjustment
import shenzhen_solitaire.card_detection.configuration as configuration
import shenzhen_solitaire.solver.board_actions as board_actions
import warnings
def drag(
src: Tuple[int, int], dst: Tuple[int, int], offset: Tuple[int, int] = (0, 0)
) -> None:
pyautogui.moveTo(x=src[0] + offset[0], y=src[1] + offset[1])
pyautogui.dragTo(
x=dst[0] + offset[0],
y=dst[1] + offset[1],
duration=0.4,
tween=lambda x: 0 if x < 0.5 else 1,
)
def click(point: Tuple[int, int], offset: Tuple[int, int] = (0, 0)) -> None:
pyautogui.moveTo(x=point[0] + offset[0], y=point[1] + offset[1])
pyautogui.mouseDown()
time.sleep(0.2)
pyautogui.mouseUp()
def handle_action(
action: board_actions.Action,
offset: Tuple[int, int],
conf: configuration.Configuration,
) -> None:
if isinstance(action, board_actions.MoveAction):
src_x, src_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.source_id,
index_y=action.source_row_index,
)
dst_x, dst_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.destination_id,
index_y=action.destination_row_index,
)
drag((src_x, src_y), (dst_x, dst_y), offset)
return
if isinstance(action, board_actions.HuaKillAction):
warnings.warn("Hua kill should be handled before handle_action")
return
if isinstance(action, board_actions.BunkerizeAction):
field_x, field_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.field_id,
index_y=action.field_row_index,
)
bunker_x, bunker_y, _, _ = adjustment.get_square(
conf.bunker_adjustment, index_x=action.bunker_id, index_y=0,
)
if action.to_bunker:
drag((field_x, field_y), (bunker_x, bunker_y), offset)
else:
drag((bunker_x, bunker_y), (field_x, field_y), offset)
return
if isinstance(action, board_actions.DragonKillAction):
dragon_sequence = [
board.SpecialCard.Zhong,
board.SpecialCard.Fa,
board.SpecialCard.Bai,
]
field_x, field_y, size_x, size_y = adjustment.get_square(
conf.special_button_adjustment,
index_x=0,
index_y=dragon_sequence.index(action.dragon),
)
click(
(field_x + (size_x - field_x) // 2, field_y + (size_y - field_y) // 2),
offset,
)
time.sleep(0.5)
return
if isinstance(action, board_actions.GoalAction):
dst_x, dst_y, _, _ = adjustment.get_square(
conf.goal_adjustment, index_x=action.goal_id, index_y=0,
)
if action.source_position == board.Position.Field:
assert action.source_row_index is not None
src_x, src_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.source_id,
index_y=action.source_row_index,
)
else:
assert action.source_position == board.Position.Bunker
src_x, src_y, _, _ = adjustment.get_square(
conf.bunker_adjustment, index_x=action.source_id, index_y=0,
)
drag((src_x, src_y), (dst_x, dst_y), offset)
return
raise AssertionError("You forgot an Action type")
def automatic(action: board_actions.Action) -> bool:
if isinstance(action, board_actions.HuaKillAction):
return True
if isinstance(action, board_actions.GoalAction) and action.obvious:
return True
return False
def handle_actions(
actions: List[board_actions.Action],
offset: Tuple[int, int],
conf: configuration.Configuration,
) -> None:
automatic_count = 0
for action in actions:
print(action)
if automatic(action):
automatic_count += 1
else:
time.sleep(0.5 * automatic_count)
automatic_count = 0
handle_action(action, offset, conf)

View File

@@ -1,123 +0,0 @@
import time
from typing import List, Tuple
import pyautogui
import shenzhen_solitaire.board as board
import shenzhen_solitaire.card_detection.adjustment as adjustment
import shenzhen_solitaire.card_detection.configuration as configuration
import shenzhen_solitaire.solver.board_actions as board_actions
import warnings
def drag(
src: Tuple[int, int], dst: Tuple[int, int], offset: Tuple[int, int] = (0, 0)
) -> None:
pyautogui.moveTo(x=src[0] + offset[0], y=src[1] + offset[1])
pyautogui.dragTo(
x=dst[0] + offset[0],
y=dst[1] + offset[1],
duration=0.4,
tween=lambda x: 0 if x < 0.5 else 1,
)
def click(point: Tuple[int, int], offset: Tuple[int, int] = (0, 0)) -> None:
pyautogui.moveTo(x=point[0] + offset[0], y=point[1] + offset[1])
pyautogui.mouseDown()
time.sleep(0.2)
pyautogui.mouseUp()
def handle_action(
action: board_actions.Action,
offset: Tuple[int, int],
conf: configuration.Configuration,
) -> None:
if isinstance(action, board_actions.MoveAction):
src_x, src_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.source_id,
index_y=action.source_row_index,
)
dst_x, dst_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.destination_id,
index_y=action.destination_row_index,
)
drag((src_x, src_y), (dst_x, dst_y), offset)
return
if isinstance(action, board_actions.HuaKillAction):
warnings.warn("Hua kill should be handled before handle_action")
return
if isinstance(action, board_actions.BunkerizeAction):
field_x, field_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.field_id,
index_y=action.field_row_index,
)
bunker_x, bunker_y, _, _ = adjustment.get_square(
conf.bunker_adjustment, index_x=action.bunker_id, index_y=0,
)
if action.to_bunker:
drag((field_x, field_y), (bunker_x, bunker_y), offset)
else:
drag((bunker_x, bunker_y), (field_x, field_y), offset)
return
if isinstance(action, board_actions.DragonKillAction):
dragon_sequence = [
board.SpecialCard.Zhong,
board.SpecialCard.Fa,
board.SpecialCard.Bai,
]
field_x, field_y, size_x, size_y = adjustment.get_square(
conf.special_button_adjustment,
index_x=0,
index_y=dragon_sequence.index(action.dragon),
)
click(
(field_x + (size_x - field_x) // 2, field_y + (size_y - field_y) // 2),
offset,
)
time.sleep(0.5)
return
if isinstance(action, board_actions.GoalAction):
dst_x, dst_y, _, _ = adjustment.get_square(
conf.goal_adjustment, index_x=action.goal_id, index_y=0,
)
if action.source_position == board.Position.Field:
assert action.source_row_index is not None
src_x, src_y, _, _ = adjustment.get_square(
conf.field_adjustment,
index_x=action.source_id,
index_y=action.source_row_index,
)
else:
assert action.source_position == board.Position.Bunker
src_x, src_y, _, _ = adjustment.get_square(
conf.bunker_adjustment, index_x=action.source_id, index_y=0,
)
drag((src_x, src_y), (dst_x, dst_y), offset)
return
raise AssertionError("You forgot an Action type")
def automatic(action: board_actions.Action) -> bool:
if isinstance(action, board_actions.HuaKillAction):
return True
if isinstance(action, board_actions.GoalAction) and action.obvious:
return True
return False
def handle_actions(
actions: List[board_actions.Action],
offset: Tuple[int, int],
conf: configuration.Configuration,
) -> None:
automatic_count = 0
for action in actions:
print(action)
if automatic(action):
automatic_count += 1
else:
time.sleep(0.5 * automatic_count)
automatic_count = 0
handle_action(action, offset, conf)

View File

@@ -51,7 +51,7 @@ class ActionStack:
def solve(
board: Board, *, timeout: Optional[float] = None
board: Board, *, timeout: Optional[float] = None, verbose: bool = False
) -> Iterator[List[board_actions.Action]]:
"""Solve a solitaire puzzle"""
state_set = {board.state_identifier}
@@ -85,7 +85,8 @@ def solve(
count += 1
if count > 5000:
count = 0
print(f"{time.time() - iter_start} {len(stack)} {board.goal}")
if verbose:
print(f"{time.time() - iter_start} {len(stack)} {board.goal}")
if timeout is not None and time.time() - iter_start > timeout:
return