-
Notifications
You must be signed in to change notification settings - Fork 11
/
common.py
133 lines (102 loc) · 4.96 KB
/
common.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import datetime
import logging
import sys
import time
from typing import NamedTuple, Tuple, List
import pyautogui
from PIL import ImageGrab, Image
def setup_logger(level=logging.DEBUG, disable_imported: bool = False) -> logging.Logger:
import logging.config
if disable_imported:
logging.config.dictConfig({'version': 1, 'disable_existing_loggers': True})
logger_ = logging.getLogger(__file__)
stream_handler = logging.StreamHandler(sys.stdout)
# noinspection SpellCheckingInspection
stream_handler.setFormatter(logging.Formatter("[{asctime}] [{levelname:7}] {message}", style='{'))
logger_.addHandler(stream_handler)
filehandler = logging.FileHandler(f"program_log.log")
# noinspection SpellCheckingInspection
filehandler.setFormatter(logging.Formatter("[{asctime}] [{name}.{funcName}:{lineno}] [{levelname}] {message}",
style='{'))
logger_.addHandler(filehandler)
logger_.setLevel(level)
return logger_
def is_window_active(window_title: str = "Rec Room") -> bool:
"""
Does not return before `window_title` becomes the active window
Returns true when `window_title` becomes the active window
:param window_title: The title of the window
:return: When the window becomes active
"""
if window_title not in (pyautogui.getActiveWindowTitle() or ""): # getActiveWindowTitle is sometimes `None`
print(f"Waiting for {window_title} to become the active window... ", end="\r", flush=True)
# While RecRoom window is not active, sleep
while window_title not in (pyautogui.getActiveWindowTitle() or ""):
time.sleep(0.1)
print(" " * 70, end="\r") # Empty the last line in the console
time.sleep(0.5)
return True
class Colors(NamedTuple):
text = (55, 57, 61) # The color of text in the Variable Input field (black)
white = (229, 225, 216) # The white background of the Variable Input field
green = (187, 205, 182) # The Variable Input field sometimes turns green - this is that color.
class ImageCoords(NamedTuple):
min_y: int
min_x: int
max_y: int
max_x: int
def found_colors(main_color: tuple[int, int, int], coordinates: ImageCoords) -> bool:
"""
Returns True if `main_color` is found in the given coordinates
:param main_color: The color to compare the detected color to
:param coordinates: Coordinates of the window of pixels to be checked and compared
:return: If the color in any of the pixels match the `main_color`
"""
def is_color(compare_color: tuple[int, int, int], main_color_: tuple[int, int, int], tolerance: int = 30) -> bool:
"""
Compare `compare_color` to `main_color` with a given tolerance
:param compare_color: The color that is being compared
:param main_color_: The color that is being compared
:param tolerance: How close the colors can be (1 - 255)
:return: Is `compare_color` same/similar as `main_color`
"""
return ((abs(compare_color[0] - main_color_[0]) < tolerance)
and (abs(compare_color[1] - main_color_[1]) < tolerance)
and (abs(compare_color[2] - main_color_[2]) < tolerance))
image = ImageGrab.grab()
for coords_x in range(coordinates.min_x, coordinates.max_x):
if is_color(image.getpixel((coords_x, coordinates.min_y)), main_color):
return True
return False
def color_in_coords(image: Image, color: Tuple[int, int, int], coordinates: List[Tuple[int, int]],
tolerance: int = 30) -> bool:
"""
Returns True if `main_color` is found in the given coordinates given a tolerance
:param image: The image from which the colors to compare will be taken
:param color: The color to compare the detected color to
:param coordinates: Coordinates of the window of pixels to be checked and compared
[(top_left_corner), (bottom_right_corner)]
:param tolerance: Max variation between colors
:return: If the color in any of the pixels match the `main_color`
"""
# coordinates: [
# (min_x, min_y)
# (max_x, max_y)
# ]
def is_color(compare_color_: Tuple[int, int, int]) -> bool:
"""
Compare `compare_color` to `main_color` with a given tolerance
:param compare_color_: The color that is being compared to the `main_color`
:return: Is `compare_color` same/+-tolerance as `main_color`
"""
nonlocal color, tolerance
return ((abs(compare_color_[0] - color[0]) < tolerance)
and (abs(compare_color_[1] - color[1]) < tolerance)
and (abs(compare_color_[2] - color[2]) < tolerance))
image_colors = image.load()
for y in range(coordinates[0][1], coordinates[1][1], 1):
for x in range(coordinates[0][0], coordinates[1][0], 1):
compare_color: Tuple[int, int, int] = image_colors[x, y]
if is_color(compare_color_=compare_color):
return True
return False