六周年:签到+许愿墙+每日单抽+活动任务+活动商店
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 datetime import datetime
from .headhunting import Headhunting
from .orundum import Orundum
from .shop import Shop from .shop import Shop
from .sign_in import SignIn
from .special_access import SpecialAccess from .special_access import SpecialAccess
from .task import Task from .task import Task
@ -31,10 +34,12 @@ class SignInManager:
result = True result = True
solver_list = [] solver_list = []
now = datetime.now() now = datetime.now()
if now < datetime(2025, 5, 5):
solver_list += [Task(), Shop()]
if now < datetime(2025, 6, 9): if now < datetime(2025, 6, 9):
solver_list += [SpecialAccess()] 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: for solver in solver_list:
solver.scheduler_stop_time = self.scheduler_stop_time solver.scheduler_stop_time = self.scheduler_stop_time
result = result and solver.run() result = result and solver.run()

View file

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

View file

@ -24,7 +24,7 @@ from mower.utils.solver import BaseSolver
from .utils import index_entry from .utils import index_entry
activity_name = "龙门幸运" activity_name = "育婴圣堂许愿"
class Orundum(BaseSolver): class Orundum(BaseSolver):
@ -37,7 +37,7 @@ class Orundum(BaseSolver):
def transition(self) -> bool: def transition(self) -> bool:
if (scene := self.scene()) == Scene.INDEX: 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) self.ctap(pos)
else: else:
notify(f"未找到{activity_name}签到入口") 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.solver import BaseSolver
from mower.utils.vector import sa, va, vs from mower.utils.vector import sa, va, vs
offset = (22, 167) offset = (24, 165)
task_name = "巴别塔复刻" task_name = "众生行记"
class Shop(BaseSolver): class Shop(BaseSolver):
@ -67,7 +67,7 @@ class Shop(BaseSolver):
continue continue
name = sa(((5, 5), (260, 60)), top_left) name = sa(((5, 5), (260, 60)), top_left)
name = cropimg(config.recog.gray, name) name = cropimg(config.recog.gray, name)
name = thres2(name, 127) name = thres2(name, 170)
nh, nw = name.shape nh, nw = name.shape
if cv2.countNonZero(name) > nh * nw * 0.5: if cv2.countNonZero(name) > nh * nw * 0.5:
name = cv2.bitwise_not(name) 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 from datetime import timedelta
import cv2
from mower.utils import config
from mower.utils.email import notify from mower.utils.email import notify
from mower.utils.image import cropimg
from mower.utils.scene import Scene from mower.utils.scene import Scene
from mower.utils.solver import BaseSolver from mower.utils.solver import BaseSolver
from mower.utils.vector import sa, va
from .utils import index_entry from .utils import index_entry
activity_name = "集成回顾水月" activity_name = "六周年庆典签到活动"
class SignIn(BaseSolver): class SignIn(BaseSolver):
@ -54,35 +59,37 @@ class SignIn(BaseSolver):
elif scene == Scene.ANNOUNCEMENT: elif scene == Scene.ANNOUNCEMENT:
if self.animation(): if self.animation():
return return
# top_left = 680, 500 top_left = 680, 500
# img = cropimg(config.recog.hsv, (top_left, (1800, 540))) img = cropimg(config.recog.hsv, (top_left, (1800, 540)))
# img = cv2.inRange(img, (0, 160, 200), (10, 255, 255)) img = cv2.inRange(img, (85, 100, 100), (95, 255, 255))
# contours, _ = cv2.findContours( contours, _ = cv2.findContours(
# img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
# ) )
# rect = [cv2.boundingRect(c) for c in contours] rect = [cv2.boundingRect(c) for c in contours]
# rect = [r for r in rect if r[2] > 200] rect = [r for r in rect if r[2] > 200]
# if len(rect) == 0: 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
if self.finish_email: if self.finish_email:
notify(f"{activity_name}奖励已领完") notify(f"{activity_name}奖励已领完")
return True 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: elif scene == Scene.ROGUE_AGENT:
if self.skin_email: if self.skin_email:
self.skin_email = False 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.scene import Scene
from mower.utils.solver import BaseSolver from mower.utils.solver import BaseSolver
task_name = "巴别塔复刻" task_name = "众生行记"
class Task(BaseSolver): class Task(BaseSolver):

View file

@ -303,7 +303,7 @@ class Recognizer:
self.find("operator/filter_hide") or self.find("operator/filter_show") self.find("operator/filter_hide") or self.find("operator/filter_show")
): ):
self.scene = Scene.OPERATOR_MANAGEMENT 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 self.scene = Scene.HEADHUNTING
elif self.find("read_and_agree") or self.find("next_step"): elif self.find("read_and_agree") or self.find("next_step"):
self.scene = Scene.AGREEMENT_UPDATE self.scene = Scene.AGREEMENT_UPDATE

View file

@ -25,7 +25,7 @@ color = {
"clue/title_party": (1621, 200), "clue/title_party": (1621, 200),
"confirm": (0, 683), "confirm": (0, 683),
"confirm_blue": ((1609, 990), (1724, 990)), "confirm_blue": ((1609, 990), (1724, 990)),
"contract": (1656, 698), "contract": (1655, 700),
"control_central_assistants": (39, 560), "control_central_assistants": (39, 560),
"depot/all": (875, 46), "depot/all": (875, 46),
"depot/all_in": (872, 45), "depot/all_in": (872, 45),
@ -112,7 +112,7 @@ color = {
"operator/filter_show": (1823, 46), "operator/filter_show": (1823, 46),
"operator/trust": (38, 600), "operator/trust": (38, 600),
"order_label": (404, 137), "order_label": (404, 137),
"pull_once": (1260, 950), "pull_once": (1252, 950),
"read_and_agree": (1115, 767), "read_and_agree": (1115, 767),
"recruiting_instructions": (343, 179), "recruiting_instructions": (343, 179),
"restore_all_sanity": (759, 789), "restore_all_sanity": (759, 789),
@ -196,19 +196,19 @@ color = {
"shop/trade_token_dialog": (717, 694), "shop/trade_token_dialog": (717, 694),
"sign_in/banner": (96, 468), "sign_in/banner": (96, 468),
"sign_in/collect": (1429, 875), "sign_in/collect": (1429, 875),
"sign_in/headhunting/available": (1251, 949),
"sign_in/moon_festival/moon_cake": (1216, 503), "sign_in/moon_festival/moon_cake": (1216, 503),
"sign_in/orundum/banner": (98, 921), "sign_in/orundum/banner": (100, 837),
"sign_in/orundum/choose": (1560, 775), "sign_in/orundum/choose": (1561, 776),
"sign_in/orundum/complete": (1561, 776), "sign_in/orundum/complete": (1561, 776),
"sign_in/orundum/confirm": (1561, 778), "sign_in/orundum/confirm": (1561, 778),
"sign_in/shop/banner": (564, 78), "sign_in/shop/banner": (870, 74),
"sign_in/shop/insufficient": (1573, 158),
"sign_in/shop/max": (1566, 617), "sign_in/shop/max": (1566, 617),
"sign_in/shop/price_black": (1238, 279), "sign_in/shop/price_black": (1238, 279),
"sign_in/shop/price_white": (1258, 237), "sign_in/shop/price_white": (1258, 237),
"sign_in/spring_festival/collect": (781, 953), "sign_in/spring_festival/collect": (781, 953),
"sign_in/spring_festival/receive": (834, 859), "sign_in/spring_festival/receive": (834, 859),
"sign_in/task/entry": (1609, 573), "sign_in/task/entry": (1682, 186),
"skip": (1803, 32), "skip": (1803, 32),
"sss/EC_up": (1049, 490), "sss/EC_up": (1049, 490),
"sss/action": (1641, 967), "sss/action": (1641, 967),
@ -473,6 +473,7 @@ template_matching = {
"sign_in/shop/0": (1341, 618), "sign_in/shop/0": (1341, 618),
"sign_in/shop/buy": ((1250, 800), (1390, 895)), "sign_in/shop/buy": ((1250, 800), (1390, 895)),
"sign_in/shop/entry": (1694, 443), "sign_in/shop/entry": (1694, 443),
"sign_in/shop/insufficient": ((1560, 140), (1920, 210)),
"sign_in/shop/out_of_stock": None, "sign_in/shop/out_of_stock": None,
"sign_in/shop/owned": None, "sign_in/shop/owned": None,
"sign_in/spring_festival/done": 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)): for i, (img, title) in enumerate(zip(required_images, titles)):
if img is None: if img is None:
print(f"警告:第 {i+1} 个图像 ('{title}') 为空,无法显示。") print(f"警告:第 {i + 1} 个图像 ('{title}') 为空,无法显示。")
# 可以选择绘制一个黑色方块或跳过 # 可以选择绘制一个黑色方块或跳过
plt.subplot(rows, cols, i + 1) plt.subplot(rows, cols, i + 1)
plt.imshow( plt.imshow(