六周年:签到+许愿墙+每日单抽+活动任务+活动商店
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful

This commit is contained in:
zhbaor 2025-05-01 22:02:11 +08:00
parent aaac1deaeb
commit 0cc40ad85a
20 changed files with 84 additions and 71 deletions

BIN
mower/resources/contract.png (Stored with Git LFS)

Binary file not shown.

BIN
mower/resources/sign_in/entry.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
mower/resources/sign_in/orundum/banner.png (Stored with Git LFS)

Binary file not shown.

BIN
mower/resources/sign_in/orundum/choose.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
mower/resources/sign_in/orundum/entry.png (Stored with Git LFS)

Binary file not shown.

BIN
mower/resources/sign_in/shop/banner.png (Stored with Git LFS)

Binary file not shown.

BIN
mower/resources/sign_in/shop/coin.png (Stored with Git LFS)

Binary file not shown.

BIN
mower/resources/sign_in/task/entry.png (Stored with Git LFS)

Binary file not shown.

View file

@ -18,7 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
from .headhunting import Headhunting
from .orundum import Orundum
from .shop import Shop
from .sign_in import SignIn
from .special_access import SpecialAccess
from .task import Task
@ -31,10 +34,12 @@ class SignInManager:
result = True
solver_list = []
now = datetime.now()
if now < datetime(2025, 5, 5):
solver_list += [Task(), Shop()]
if now < datetime(2025, 6, 9):
solver_list += [SpecialAccess()]
if now < datetime(2025, 5, 15):
solver_list += [SignIn(), Orundum(), Headhunting()]
if now < datetime(2025, 5, 29):
solver_list += [Task(), Shop()]
for solver in solver_list:
solver.scheduler_stop_time = self.scheduler_stop_time
result = result and solver.run()

View file

@ -31,8 +31,8 @@ class Headhunting(BaseSolver):
if (scene := self.scene()) == Scene.HEADHUNTING:
if self.animation():
return
if self.find("sign_in/headhunting/available"):
self.tap("pull_once")
if pos := self.find("sign_in/headhunting/available"):
self.tap(pos)
else:
notify("今日赠送单抽已抽完")
return True

View file

@ -24,7 +24,7 @@ from mower.utils.solver import BaseSolver
from .utils import index_entry
activity_name = "龙门幸运"
activity_name = "育婴圣堂许愿"
class Orundum(BaseSolver):
@ -37,7 +37,7 @@ class Orundum(BaseSolver):
def transition(self) -> bool:
if (scene := self.scene()) == Scene.INDEX:
if pos := index_entry("sign_in/orundum/entry", "幸运墙登录活动"):
if pos := index_entry("sign_in/orundum/entry", activity_name):
self.ctap(pos)
else:
notify(f"未找到{activity_name}签到入口")

View file

@ -30,8 +30,8 @@ from mower.utils.scene import Scene
from mower.utils.solver import BaseSolver
from mower.utils.vector import sa, va, vs
offset = (22, 167)
task_name = "巴别塔复刻"
offset = (24, 165)
task_name = "众生行记"
class Shop(BaseSolver):
@ -67,7 +67,7 @@ class Shop(BaseSolver):
continue
name = sa(((5, 5), (260, 60)), top_left)
name = cropimg(config.recog.gray, name)
name = thres2(name, 127)
name = thres2(name, 170)
nh, nw = name.shape
if cv2.countNonZero(name) > nh * nw * 0.5:
name = cv2.bitwise_not(name)

View file

@ -18,13 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import timedelta
import cv2
from mower.utils import config
from mower.utils.email import notify
from mower.utils.image import cropimg
from mower.utils.scene import Scene
from mower.utils.solver import BaseSolver
from mower.utils.vector import sa, va
from .utils import index_entry
activity_name = "集成回顾水月"
activity_name = "六周年庆典签到活动"
class SignIn(BaseSolver):
@ -54,35 +59,37 @@ class SignIn(BaseSolver):
elif scene == Scene.ANNOUNCEMENT:
if self.animation():
return
# top_left = 680, 500
# img = cropimg(config.recog.hsv, (top_left, (1800, 540)))
# img = cv2.inRange(img, (0, 160, 200), (10, 255, 255))
# contours, _ = cv2.findContours(
# img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
# )
# rect = [cv2.boundingRect(c) for c in contours]
# rect = [r for r in rect if r[2] > 200]
# if len(rect) == 0:
# if not self.in_progress:
# notify(f"{activity_name}奖励已领完")
# return True
# rect.sort(key=lambda c: c[0])
# x, y, w, h = rect[0]
# scope = sa(((x, y), (x + w, y + h)), top_left)
# self.in_progress = True
# self.ctap(scope)
if not self.find("sign_in/banner"):
self.scene_graph_step(Scene.INDEX)
return
if pos := self.find("sign_in/collect"):
if self.ctap(pos, 5):
self.materiel_email = True
self.skin_email = True
self.finish_email = False
return
top_left = 680, 500
img = cropimg(config.recog.hsv, (top_left, (1800, 540)))
img = cv2.inRange(img, (85, 100, 100), (95, 255, 255))
contours, _ = cv2.findContours(
img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
rect = [cv2.boundingRect(c) for c in contours]
rect = [r for r in rect if r[2] > 200]
if len(rect) == 0:
if self.finish_email:
notify(f"{activity_name}奖励已领完")
return True
rect.sort(key=lambda c: c[0])
x, y, w, h = rect[0]
scope = sa(((x, y), va((x, y), (w, h))), top_left)
if self.ctap(scope):
self.materiel_email = True
self.skin_email = True
self.finish_email = False
# if not self.find("sign_in/banner"):
# self.scene_graph_step(Scene.INDEX)
# return
# if pos := self.find("sign_in/collect"):
# if self.ctap(pos, 5):
# self.materiel_email = True
# self.skin_email = True
# self.finish_email = False
# return
# if self.finish_email:
# notify(f"{activity_name}奖励已领完")
# return True
elif scene == Scene.ROGUE_AGENT:
if self.skin_email:
self.skin_email = False

View file

@ -25,7 +25,7 @@ from mower.utils.rapidocr import ocr_rec
from mower.utils.scene import Scene
from mower.utils.solver import BaseSolver
task_name = "巴别塔复刻"
task_name = "众生行记"
class Task(BaseSolver):

View file

@ -303,7 +303,7 @@ class Recognizer:
self.find("operator/filter_hide") or self.find("operator/filter_show")
):
self.scene = Scene.OPERATOR_MANAGEMENT
elif self.find("pull_once"):
elif self.find("pull_once") or self.find("sign_in/headhunting/available"):
self.scene = Scene.HEADHUNTING
elif self.find("read_and_agree") or self.find("next_step"):
self.scene = Scene.AGREEMENT_UPDATE

View file

@ -25,7 +25,7 @@ color = {
"clue/title_party": (1621, 200),
"confirm": (0, 683),
"confirm_blue": ((1609, 990), (1724, 990)),
"contract": (1656, 698),
"contract": (1655, 700),
"control_central_assistants": (39, 560),
"depot/all": (875, 46),
"depot/all_in": (872, 45),
@ -112,7 +112,7 @@ color = {
"operator/filter_show": (1823, 46),
"operator/trust": (38, 600),
"order_label": (404, 137),
"pull_once": (1260, 950),
"pull_once": (1252, 950),
"read_and_agree": (1115, 767),
"recruiting_instructions": (343, 179),
"restore_all_sanity": (759, 789),
@ -196,19 +196,19 @@ color = {
"shop/trade_token_dialog": (717, 694),
"sign_in/banner": (96, 468),
"sign_in/collect": (1429, 875),
"sign_in/headhunting/available": (1251, 949),
"sign_in/moon_festival/moon_cake": (1216, 503),
"sign_in/orundum/banner": (98, 921),
"sign_in/orundum/choose": (1560, 775),
"sign_in/orundum/banner": (100, 837),
"sign_in/orundum/choose": (1561, 776),
"sign_in/orundum/complete": (1561, 776),
"sign_in/orundum/confirm": (1561, 778),
"sign_in/shop/banner": (564, 78),
"sign_in/shop/insufficient": (1573, 158),
"sign_in/shop/banner": (870, 74),
"sign_in/shop/max": (1566, 617),
"sign_in/shop/price_black": (1238, 279),
"sign_in/shop/price_white": (1258, 237),
"sign_in/spring_festival/collect": (781, 953),
"sign_in/spring_festival/receive": (834, 859),
"sign_in/task/entry": (1609, 573),
"sign_in/task/entry": (1682, 186),
"skip": (1803, 32),
"sss/EC_up": (1049, 490),
"sss/action": (1641, 967),
@ -473,6 +473,7 @@ template_matching = {
"sign_in/shop/0": (1341, 618),
"sign_in/shop/buy": ((1250, 800), (1390, 895)),
"sign_in/shop/entry": (1694, 443),
"sign_in/shop/insufficient": ((1560, 140), (1920, 210)),
"sign_in/shop/out_of_stock": None,
"sign_in/shop/owned": None,
"sign_in/spring_festival/done": None,

View file

@ -531,7 +531,7 @@ if __name__ == "__main__":
for i, (img, title) in enumerate(zip(required_images, titles)):
if img is None:
print(f"警告:第 {i+1} 个图像 ('{title}') 为空,无法显示。")
print(f"警告:第 {i + 1} 个图像 ('{title}') 为空,无法显示。")
# 可以选择绘制一个黑色方块或跳过
plt.subplot(rows, cols, i + 1)
plt.imshow(