Files
shenzhen-solitaire/shenzhen_solitaire/clicker/__init__.py
2020-06-12 22:40:58 +02:00

134 lines
3.8 KiB
Python

import time
from typing import List, Tuple, Dict, Any
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 warnings
from dataclasses import dataclass
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 dragSquare(
src: Tuple[int, int, int, int],
dst: Tuple[int, int, int, int],
offset: Tuple[int, int] = (0, 0),
) -> None:
drag(
(src[0] + (src[2] - src[0]) // 2, src[1] + (src[3] - src[1]) // 2),
(dst[0] + (dst[2] - dst[0]) // 2, dst[1] + (dst[3] - dst[1]) // 2),
offset,
)
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 clickSquare(
field: Tuple[int, int, int, int], offset: Tuple[int, int] = (0, 0)
) -> None:
click(
(field[0] + (field[2] - field[0]) // 2, field[1] + (field[3] - field[1]) // 2),
offset,
)
@dataclass
class DragAction:
source: Tuple[int, int]
destination: Tuple[int, int]
@dataclass
class ClickAction:
destination: Tuple[int, int]
class WaitAction:
pass
def _parse_field(
field: Dict[str, Any], conf: configuration.Configuration
) -> Tuple[int, int]:
return (
int(field["column"]) * conf.field_adjustment.dx + conf.field_adjustment.x,
int(field["row"]) * conf.field_adjustment.dy + conf.field_adjustment.y,
)
def parse_action(action: Dict[str, Any], conf: configuration.Configuration):
assert len(action) == 1
action_name, info = next(iter(action.items()))
action_name = action_name.lower()
if action_name == "bunkerize":
field = _parse_field(info["field_position"], conf)
bunker = (
int(info["bunker_slot_index"]) * conf.bunker_adjustment.dx
+ conf.bunker_adjustment.x,
conf.bunker_adjustment.y,
)
if str(info["to_bunker"]).lower() == "true":
return DragAction(source=field, destination=bunker)
else:
return DragAction(source=bunker, destination=field)
elif action_name == "move":
return DragAction(
source=_parse_field(info["source"], conf),
destination=_parse_field(info["source"], conf),
)
elif action_name == "dragonkill":
return ClickAction()
elif action_name == "goal":
goal = (
int(info["goal_slot_index"]) * conf.goal_adjustment.dx
+ conf.goal_adjustment.x,
conf.goal_adjustment.y,
)
if "Field" in info["source"]:
source = _parse_field(info["source"]["Field"], conf)
else:
source = (
int(info["source"]["Bunker"]["slot_index"]) * conf.bunker_adjustment.dx
+ conf.bunker_adjustment.x,
conf.bunker_adjustment.y,
)
return DragAction(source=source, destination=goal)
elif action_name == "huakill":
return WaitAction()
def handle_actions(
actions: List[Dict[str, Dict[str, Any]]],
offset: Tuple[int, int],
conf: configuration.Configuration,
) -> None:
automatic_count = 0
for action in actions:
print(action)
if isinstance(action, board_actions.HuaKillAction):
automatic_count += 1
else:
time.sleep(0.5 * automatic_count)
automatic_count = 0
handle_action(action, offset, conf)
time.sleep(0.5 * automatic_count)