Compare commits

...

58 commits

Author SHA1 Message Date
21fd28fc46 选技能Solver及其他细节
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-10 18:44:53 +08:00
275fbb692c OPERATOR_SELECT改为寻找choose_agent/fast_select ope_select_start改为模板匹配 2024-10-10 16:49:18 +08:00
52f0a667e6 Merge remote-tracking branch 'origin/dev_battle' into dev_battle 2024-10-10 14:30:06 +08:00
5bcdb0cb79 补充图片
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-10 14:12:18 +08:00
fe00ce0028 使用指定技能支持关闭弹药类技能
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-10 14:11:12 +08:00
69ccb6bdfe 支持中文版action 2024-10-10 12:55:52 +08:00
daf2a4bdbf 自动战斗跳过剧情
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 23:00:00 +08:00
ddb3aa5c30 recognize/data排序;navigation/activity/banner改为模板匹配 2024-10-09 22:29:25 +08:00
8c2b267454 借助战适配新版ui
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 19:02:44 +08:00
462b26a788 fix:补充提交资源
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 18:24:42 +08:00
2e3312c868 ruff格式化
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 18:17:07 +08:00
795cb950ea perf:修改图片资源
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
2024-10-09 17:58:06 +08:00
43db048a10 add:追逐日落以西导航
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
2024-10-09 17:48:38 +08:00
c70cb4e20d Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
2024-10-09 17:22:52 +08:00
52c97039d5 Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng 2024-10-09 17:22:18 +08:00
1f7ae69803 更正key_mapping相关代码
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
2024-10-09 17:22:13 +08:00
d3a7d595d5 Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 17:21:10 +08:00
72d44ebaf2 action支持BulletTime 2024-10-09 17:21:08 +08:00
1cea182615 补充提交 三个缺失干员 2024-10-09 17:21:07 +08:00
d8cd546d66 补充CreditFight的导航模式 2024-10-09 17:20:11 +08:00
862db241fb 将更新watching移到战斗loading中 2024-10-09 14:48:01 +08:00
833603e0d5 AutoFight支持干员组(未测试)
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 14:12:11 +08:00
becc9cbfcf 前端更新
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 12:56:19 +08:00
a21ff44d31 更新submodule 2024-10-09 12:53:46 +08:00
a0f54ab51f Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-09 12:52:58 +08:00
6b7703ae99 资源更新 无新干员头像 2024-10-09 12:52:54 +08:00
9c4b54a417 支持大部分action
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 23:44:14 +08:00
456539d7a5 分离action开始的前置条件 2024-10-08 23:43:21 +08:00
c9f56c2435 优化drag_success与deploy 2024-10-08 23:39:34 +08:00
dff8a3d27e drag_success和deploy改进
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 18:08:18 +08:00
81c8840691 部署干员过程中识别拖拽是否成功
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 15:14:55 +08:00
d0172de138 上传生成的requirements
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 12:06:36 +08:00
27b492512b 上传依赖
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 11:59:52 +08:00
e7246e4add 删除不需要的导入
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 11:48:20 +08:00
03b6f8134f 读取基建报表使用数据库/使用ORM简化操作 2024-10-08 11:47:20 +08:00
f89d535156 arrange_confirm改为模板匹配
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 10:03:56 +08:00
ead4ee3db4 Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 09:31:45 +08:00
423013d0cd depotREC.py捕获所有异常 2024-10-08 09:31:42 +08:00
0a4c902b1d fix:订单读取时间错误
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-08 08:34:07 +08:00
bd543e9130 补充CreditFight和LastStageNavigation
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-07 21:05:11 +08:00
83372c9751 AutoFight使用场景图分类并导航到对应关卡
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-07 20:24:26 +08:00
125464dc42 NavigationSolver分为代理与抄作业 2024-10-07 20:23:02 +08:00
d7b60c4cb3 一种很新的截图方法
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-07 10:57:21 +08:00
3da7309610 Ruff格式化代码
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-07 09:08:15 +08:00
f19f3cd563 头像背景改为黑色
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
2024-10-06 18:57:27 +08:00
b68ada9252 “作战中”场景与识别 2024-10-06 16:36:54 +08:00
084254a7de 排班表默认配置 最大组人数设置为0 2024-10-06 09:46:50 +08:00
9cd8310492 修改计时器
Some checks failed
ci/woodpecker/push/check_format Pipeline failed
2024-10-05 16:51:28 +08:00
aa3009230d 尝试使用数据库存取仓库数据 2024-10-05 16:42:52 +08:00
28cf4d7065 fix:订单时间读取错误造成误判漏单
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-05 16:37:56 +08:00
890efff953 整理requirements.in
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-05 15:18:52 +08:00
ff8a7dd020 补充依赖
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-05 11:25:19 +08:00
cbd6bf6cce Merge branch 'main' of https://git.zhaozuohong.vip/mower-ng/mower-ng
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-05 11:24:27 +08:00
92e866e195 修复了由于YJ修改登陆接口导致无法正确登陆的问题/扫仓库同时使用图像识别/整理森空岛部分的代码 2024-10-05 11:24:05 +08:00
5be6361f97 perf:更新刷理智周计划的说明
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-05 09:58:34 +08:00
d1729eaec3 用match2d找控制中枢
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-03 22:43:53 +08:00
95dad2e7a8 登录中场景识别改进
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-10-03 22:15:43 +08:00
897e04ab5f vector.sm返回前取整 2024-10-03 22:07:46 +08:00
114 changed files with 2784 additions and 5854 deletions

@ -1 +1 @@
Subproject commit 24adddd8dda499804b48f687f3461363cf1706c8
Subproject commit e1d67db2ed5cfe484c56ecf10cbf2ff294184fab

View file

@ -0,0 +1,67 @@
import ctypes
import time
import cv2
import numpy as np
# 加载动态链接库
external_renderer = ctypes.CDLL(
"C:\\Program Files\\NetEase\\MuMu Player 12\\shell\\sdk\\external_renderer_ipc.dll"
)
# 定义函数原型
external_renderer.nemu_connect.argtypes = [ctypes.c_wchar_p, ctypes.c_int]
external_renderer.nemu_connect.restype = ctypes.c_int
external_renderer.nemu_disconnect.argtypes = [ctypes.c_int]
external_renderer.nemu_disconnect.restype = None
external_renderer.nemu_capture_display.argtypes = [
ctypes.c_int,
ctypes.c_uint,
ctypes.c_int,
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_ubyte),
]
external_renderer.nemu_capture_display.restype = ctypes.c_int
# 设置 emulator 路径和实例
install_path = ctypes.c_wchar_p("C:\\Program Files\\NetEase\\MuMu Player 12")
instance_index = 0
# 连接到 emulator
connection = external_renderer.nemu_connect(install_path, instance_index)
if connection == 0:
print("连接失败,请确认安装目录正确且实例已经打开")
else:
print("连接成功")
pixels = (ctypes.c_ubyte * 8294400)()
start_time = time.time()
external_renderer.nemu_capture_display(
connection,
0,
8294400,
ctypes.byref(ctypes.c_int(1920)),
ctypes.byref(ctypes.c_int(1080)),
pixels,
)
image = np.frombuffer(pixels, dtype=np.uint8).reshape((1080, 1920, 4))[
:, :, :3
] # RGBA-RGB
image = np.flipud(image) # 翻转
print(f"像素转换为矩阵:{time.time() - start_time:.4f}")
image_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
print(f"OpenCV转换BGR耗时{time.time() - start_time:.4f}")
cv2.imwrite("screenshot.png", image_bgr)
print(f"截图已保存,耗时:{time.time() - start_time:.4f}")
# 断开连接
external_renderer.nemu_disconnect(connection)

View file

@ -87,8 +87,8 @@ class Arknights数据处理器:
匹配结果 = True
return 匹配结果
self.物品_名称对1 = {}
self.物品_名称对 = {}
if not os.path.exists("./ui/public/depot/EXP.webp"):
png_image = Image.open("./ArknightsGameResource/item/EXP_PLAYER.png")
png_image.save("./ui/public/depot/EXP.webp", "WEBP")
@ -111,13 +111,14 @@ class Arknights数据处理器:
png_image = Image.open(源文件路径)
png_image.save(目标文件路径, "WEBP")
templist = [物品代码, 图标代码, 中文名称, 分类类型, 排序代码]
self.物品_名称对[物品代码] = templist
self.物品_名称对1[物品代码] = templist
self.物品_名称对[中文名称] = templist
self.物品_名称对[物品代码] = templist
print(f"复制 {源文件路径}{目标文件路径}")
else:
print(f"可以复制,但是未找到: {源文件路径}")
with open("./mower/data/key_mapping.json", "w", encoding="utf8") as json_file:
json.dump(self.物品_名称对, json_file, ensure_ascii=False, indent=4)
json.dump(self.物品_名称对1, json_file, ensure_ascii=False, indent=4)
print()
def 添加干员(self):
@ -126,7 +127,6 @@ class Arknights数据处理器:
for 干员代码, 干员数据 in self.干员表.items():
if not 干员数据["itemObtainApproach"]:
continue
干员名 = 干员数据["name"]
干员_名称列表[干员名] = {
"key": 干员代码,
@ -496,7 +496,8 @@ class Arknights数据处理器:
# k: Lancet-2
if i.startswith(j):
img = loadimg(os.path.join(data_path, i), True, bg)
img = cropimg(img, crop)
if crop is not None:
img = cropimg(img, crop)
kp, des = ORB.detectAndCompute(img, None)
if k not in data:
data[k] = []
@ -505,7 +506,7 @@ class Arknights数据处理器:
with lzma.open(f"./mower/models/{name}.pkl", "wb") as f:
pickle.dump(data, f)
extract("avatar", "WHITE", ((47, 46), (147, 146)))
extract("avatar", "BLACK", None)
extract("portrait", (140, 140, 140, 255), ((0, 85), (180, 195)))
def 获得干员基建描述(self):

View file

@ -1,16 +1,15 @@
import json
import os
from datetime import datetime, timedelta
from evalidate import Expr
from mower.solvers.base_schedule import BaseSchedulerSolver
from mower.solvers.depot_reader import DepotManager
from mower.solvers.reclamation_algorithm import ReclamationAlgorithm
from mower.solvers.secret_front import SecretFront
from mower.utils import config, path, rapidocr
from mower.utils.csleep import MowerExit
from mower.utils.datetime import format_time
from mower.utils.depot import 创建csv, 创建json
from mower.utils.device.adb_client.session import Session
from mower.utils.device.scrcpy import Scrcpy
from mower.utils.email import send_message, task_template
@ -242,22 +241,8 @@ def simulate():
# 应该在maa任务之后
def _is_depotscan():
import pandas as pd
path = get_path("@app/tmp/depotresult.csv")
if os.path.exists(path):
depotinfo = pd.read_csv(path)
仓库识别时间戳 = depotinfo.iloc[-1, 0]
return int(仓库识别时间戳)
else:
logger.info(f"{path} 不存在,新建一个存储仓库物品的csv")
now_time = (
int(datetime.now().timestamp())
- config.conf.maa_gap * 3600
)
创建csv()
创建json()
return now_time
depot_manager = DepotManager()
return depot_manager.读取仓库()[-1]
if config.conf.maa_depot_enable:
dt = int(datetime.now().timestamp()) - _is_depotscan()

View file

@ -1351,4 +1351,4 @@
"key": "char_486_takila",
"profession": "WARRIOR"
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -37,7 +37,7 @@
},
"7": {
"label": "SKIP",
"comment": "跳过"
"comment": "开包动画"
},
"8": {
"label": "DOUBLE_CONFIRM",
@ -75,6 +75,14 @@
"label": "INDEX_SANITY",
"comment": "首页源石换理智"
},
"17": {
"label": "STORY",
"comment": "作战剧情"
},
"18": {
"label": "STORY_SKIP",
"comment": "作战剧情"
},
"101": {
"label": "LOGIN_MAIN",
"comment": "登录页面"
@ -369,13 +377,17 @@
"comment": "借助战"
},
"616": {
"label": "OPERATOR_STRANGER_SUPPORT",
"comment": "使用非好友助战"
"label": "OPERATOR_SUPPORT_AGENT",
"comment": "使用助战干员界面"
},
"617": {
"label": "OPERATOR_AGENT_SELECT",
"comment": "作战干员选择界面"
},
"618": {
"label": "OPERATOR_FIGHT",
"comment": "作战中"
},
"701": {
"label": "SHOP_OTHERS",
"comment": "商店其它界面"

BIN
mower/models/CONSUME.pkl (Stored with Git LFS)

Binary file not shown.

BIN
mower/models/MATERIAL.pkl (Stored with Git LFS)

Binary file not shown.

BIN
mower/models/NORMAL.pkl (Stored with Git LFS)

Binary file not shown.

BIN
mower/models/avatar.pkl (Stored with Git LFS)

Binary file not shown.

BIN
mower/models/levels.pkl (Stored with Git LFS)

Binary file not shown.

BIN
mower/models/operator_room.model (Stored with Git LFS)

Binary file not shown.

BIN
mower/models/portrait.pkl (Stored with Git LFS)

Binary file not shown.

BIN
mower/models/recruit_result.pkl (Stored with Git LFS)

Binary file not shown.

BIN
mower/resources/fight/gear.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/fight/light.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/fight/skill_be_choosen.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/fight/skill_stop.png (Stored with Git LFS) Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

After

Width:  |  Height:  |  Size: 274 KiB

BIN
mower/resources/story_skip.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/story_skip_confirm_dialog.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -5,38 +5,64 @@ from scipy.signal import argrelmax
from skimage.metrics import structural_similarity
from mower.models import secret_front
from mower.solvers.navigation import NavigationSolver
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.character_recognize import match_avatar
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, loadres, thres2
from mower.utils.log import logger
from mower.utils.solver import BaseSolver
from mower.utils.scene import Scene
from mower.utils.tile_pos import Calc, find_level
from mower.utils.vector import sa, va
class AutoFight(BaseSolver):
def run(self, level_name, opers, actions):
class AutoFight(SceneGraphSolver):
def run(self, level_name, opers, actions, groups=None):
logger.info("Start: 自动战斗")
logger.info("地图坐标计算https://github.com/yuanyan3060/Arknights-Tile-Pos")
self.level_name = level_name
level = find_level(level_name, None)
self.calc = Calc(1920, 1080, level)
self.actions = actions
self.actions = actions # 行动列表
self.opers = opers # 干员列表
self.groups = groups # 干员组
self.speed = 1 # 一倍/二倍速
self.loading = True # 等待加载
self.playing = True # 暂停/继续
self.Bullet_Time = False # 是否选中干员进入1/5速度
self.Skill_Daemon = False # 开始挂机使用技能
self.condition_satified = False # 前置条件是否满足
self.operators = {} # 可部署的干员
self.location = {} # 干员部署坐标
self.post_delay = 0 # 行动后等待时间
self.watching = {} # 需要开技能的干员
for op in opers:
self.replacements = {} # 将干员组的名字替换为对应干员
super().run()
def find_and_change_group_name(self, name: str) -> str:
if name in self.replacements:
return self.replacements[name]
for group in self.groups:
if group["name"] == name:
for op in group["opers"]:
if op["name"] in self.operators:
self.replacements[name] = op["name"]
name = op["name"]
del op["name"]
self.watching[name] = op
self.watching[name]["location"] = None
del group
return name
return name
def update_watching(self):
for op in self.opers:
name = op["name"]
del op["name"]
self.watching[name] = op
self.watching[name]["location"] = None
super().run()
def number(self, scope: tp.Scope, height: int, thres: int) -> int:
"数字识别"
img = cropimg(config.recog.gray, scope)
@ -84,6 +110,57 @@ class AutoFight(BaseSolver):
logger.debug(kills)
return kills
def CD(self) -> int:
"获取进入CD的干员数量"
config.recog.update()
y = 887
img = cropimg(config.recog.gray, ((0, y), (1920, 905)))
threshold = 0.7
c = loadres("fight/c", True)
mask = loadres("fight/c_mask", True)
result = cv2.matchTemplate(img, c, cv2.TM_CCOEFF_NORMED, None, mask)[0]
op = []
for i in argrelmax(result, order=50)[0]:
if result[i] > threshold:
op.append(i)
self.operators = {}
number = 0
for x in op:
# 看最下方条的颜色判断是否正在转CD
bar_scope = sa(((-20, 187), (10, 190)), (x, y))
img = cropimg(config.recog.img, bar_scope)
img = cv2.inRange(img, (1, 0, 0), (3, 255, 255))
count = cv2.countNonZero(img)
logger.debug(count)
if count > 50:
number += 1
return number
def sleep_post_delay(self):
self.sleep(self.post_delay)
self.post_delay = 0
def check_condition(self) -> bool:
if "kills" in self.action and self.action["kills"] > self.kills():
return False
if "costs" in self.action and self.action["costs"] > self.cost():
return False
if "cooling" in self.action and self.action["cooling"] > self.CD():
return False
if "cost_changes" in self.action:
s = self.cost()
while self.cost() - s < self.action["cost_changes"]:
self.sleep(0.5)
if "pre_delay" in self.action:
self.sleep(self.action["pre_delay"] / 1000)
if "post_delay" in self.action:
self.pre_delay = self.action["post_delay"] / 1000
if self.Bullet_Time:
self.tap((400, 100))
self.sleep(0.3)
self.Bullet_Time = False
return True
def skill_ready(self, x: int, y: int) -> bool:
"""指定坐标的干员技能是否可以开启
@ -101,38 +178,22 @@ class AutoFight(BaseSolver):
logger.debug(f"{min_val=} {min_loc=}")
return min_val <= 0.2
def in_fight(self) -> bool:
"是否在战斗中"
img = cropimg(config.recog.img, ((725, 16), (797, 76)))
img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
img = cv2.inRange(img, (12, 0, 0), (16, 255, 255))
tpl = loadres("fight/enemy", True)
result = cv2.matchTemplate(img, tpl, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
value = 0.4
logger.debug(f"{min_val}小于{value}则判定在战斗")
return min_val < value
def skill_stop(self, x: int, y: int) -> bool:
"""指定坐标的干员技能是否可以关闭
def battle_complete(self) -> bool:
"识别行动是否结束"
img = cropimg(config.recog.gray, ((87, 268), (529, 383)))
img = thres2(img, 200)
tpl = loadres("fight/complete", True)
result = cv2.matchTemplate(img, tpl, cv2.TM_SQDIFF_NORMED)
Args:
x: 横坐标
y: 纵坐标
"""
skill_stop = loadres("fight/skill_stop")
h, w, _ = skill_stop.shape
pos = self.calc.get_character_screen_pos(x, y, False, False)
pos = int(pos.x), int(pos.y)
img = cropimg(config.recog.img, sa(((-15, -168), (15, -138)), pos))
result = cv2.matchTemplate(img, skill_stop, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
value = 0.4
logger.debug(f"{min_val}小于{value}则判定行动结束/胜利")
return min_val < value
def battle_fail(self) -> bool:
"识别行动是否失败"
img = cropimg(config.recog.gray, ((1129, 455), (1626, 531)))
tpl = loadres("fight/failed_text", True)
result = cv2.matchTemplate(img, tpl, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
value = 0.05
logger.debug(f"{min_val}小于{value}则判定行动失败")
return min_val < value # 测试时数值很低基本为0或有其他方法
logger.debug(f"{min_val=} {min_loc=}")
return min_val <= 0.2
def update_operators(self):
"识别可部署的干员"
@ -179,6 +240,9 @@ class AutoFight(BaseSolver):
def complete_action(self):
"完成当前行动"
self.actions.pop(0)
self.condition_satified = False
if self.post_delay > 0:
self.sleep_post_delay()
def toggle_play(self):
"切换暂停与继续"
@ -209,11 +273,36 @@ class AutoFight(BaseSolver):
self.speed = target
self.complete_action()
def bullet_time(self):
"选中干员进入1/5速度"
if "name" in self.action:
name = self.action["name"]
x, y = self.location[name]
self.location[name] = None
else:
x, y = self.action["location"]
self.select(x, y)
self.Bullet_Time = True
self.complete_action()
def drag_success(self):
img = thres2(config.recog.gray, 200)
contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
rect = [cv2.boundingRect(c) for c in contours]
left = min(x for x, y, w, h in rect if w > 40 and h > 40)
right = max(x + w for x, y, w, h in rect if w > 40 and h > 40)
top = min(y for x, y, w, h in rect if w > 40 and h > 40)
bottom = max(y + h for x, y, w, h in rect if w > 40 and h > 40)
width = right - left
height = bottom - top
logger.debug(f"{width=} {height=}")
return width < 900 and height < 850
def deploy(self):
"部署干员"
if "kills" in self.action and self.action["kills"] < self.kills():
return
name = self.action["name"]
if self.groups or self.replacements:
name = self.find_and_change_group_name(name)
if name not in self.operators:
self.update_operators()
return
@ -226,21 +315,35 @@ class AutoFight(BaseSolver):
pos = int(pos.x), int(pos.y)
direction = self.action["direction"]
logger.info(f"在({x}, {y})部署{name},方向为{direction}")
if direction in ["Left"]:
if direction in ["Left", ""]:
dir = (-200, 0)
elif direction in ["Right"]:
elif direction in ["Right", ""]:
dir = (200, 0)
elif direction in ["Up"]:
elif direction in ["Up", ""]:
dir = (0, -200)
else:
dir = (0, 200)
dir = va(pos, dir)
config.device.swipe_ext([start, top, pos], [100, 500], up_wait=400)
sleep(0.1)
config.device.swipe_ext([pos, dir], [200])
self.operators = {}
self.complete_action()
self.location[name] = x, y
if direction in ["None", ""]:
self.operators = {}
self.complete_action()
self.location[name] = x, y
return
for _ in range(6):
if not (flag := self.drag_success()):
self.sleep(0.05)
else:
break
if flag:
config.device.swipe_ext([pos, dir], [200])
self.operators = {}
self.complete_action()
self.location[name] = x, y
else:
self.ctap(va(pos, (-300, -300)), 0.5, config.screenshot_avg / 1000)
def select(self, x: int, y: int):
"选中干员"
@ -250,10 +353,12 @@ class AutoFight(BaseSolver):
def withdraw(self):
"撤下干员"
if "kills" in self.action and self.action["kills"] < self.kills():
return
name = self.action["name"]
x, y = self.location[name]
if "name" in self.action:
name = self.action["name"]
x, y = self.location[name]
self.location[name] = None
else:
x, y = self.action["location"]
self.select(x, y)
sleep(0.5)
pos = self.calc.get_with_draw_screen_pos(x, y)
@ -272,45 +377,92 @@ class AutoFight(BaseSolver):
config.device.tap(pos)
sleep(0.5)
def action_skill(self):
"使用action中指定位置的技能"
if flag := ("name" in self.action):
name = self.action["name"]
x, y = self.location[name]
else:
x, y = self.action["location"]
if self.skill_ready(x, y) or self.skill_stop(x, y):
self.use_skill(x, y)
if flag and self.watching[self.action["name"]]["skill_usage"] == 2:
self.watching[self.action["name"]]["skill_times"] -= 1
if self.watching[self.action["name"]]["skill_times"] <= 0:
del self.watching[self.action["name"]]
self.complete_action()
def transition(self):
config.recog.update()
if not self.in_fight():
if self.battle_fail():
logger.warning("行动失败,请检查干员/练度")
return True
elif self.battle_complete():
logger.info("行动结束")
return True
else:
sleep(2)
if (scene := self.scene()) == Scene.OPERATOR_FIGHT:
if self.loading:
self.pause()
self.loading = False
self.update_operators()
self.update_watching()
self.play()
return
# if self.action is None:
# self.sleep(10)
# return
if self.loading:
self.pause()
self.loading = False
self.update_operators()
self.play()
return
if self.playing:
for w, d in self.watching.items():
if w not in self.location:
continue
x, y = self.location[w]
if self.skill_ready(x, y):
self.use_skill(x, y)
if d["skill_usage"] == 2:
d["skill_times"] -= 1
if d["skill_times"] <= 0:
del self.watching[w]
return
if self.Skill_Daemon:
for w, d in self.watching.items():
if w not in self.location or d["skill_usage"] == 0:
continue
x, y = self.location[w]
if self.skill_ready(x, y):
self.use_skill(x, y)
if d["skill_usage"] == 2:
d["skill_times"] -= 1
if d["skill_times"] <= 0:
del self.watching[w]
return
if self.action is None:
self.sleep(1)
return
if not self.condition_satified:
self.condition_satified = self.check_condition()
return
if self.action["type"] in ["SpeedUp", "二倍速"]:
self.toggle_speed()
elif self.action["type"] in ["Deploy", "部署"]:
self.deploy()
elif self.action["type"] in ["Retreat", "撤退"]:
self.withdraw()
elif self.action["type"] in ["Skill", "技能"]:
self.action_skill()
elif self.action["type"] in ["SkillDaemon", "摆完挂机"]:
self.Skill_Daemon = True
self.complete_action()
elif self.action["type"] in ["SkillUsage", "技能用法"]:
self.watching[self.action["name"]]["skill_usage"] = self.action[
"skill_usage"
]
self.complete_action()
elif self.action["type"] in ["BulletTime", "子弹时间"]:
self.bullet_time()
if self.action["type"] == "SpeedUp":
self.toggle_speed()
elif self.action["type"] == "Deploy":
self.deploy()
elif self.action["type"] == "Retreat":
self.withdraw()
elif self.action["type"] in ["Output", "打印"]:
self.complete_action()
elif scene == Scene.OPERATOR_FAILED:
logger.warning("行动失败,请检查干员/练度")
return True
elif scene == Scene.OPERATOR_FINISH:
logger.info("行动结束")
return True
elif scene == Scene.CONFIRM:
logger.warning("被顶号")
return True
elif scene in self.waiting_scene:
self.waiting_solver()
elif scene == Scene.OPERATOR_SELECT:
self.tap((1655, 781))
elif scene == Scene.STORY:
self.tap_element("story_skip")
elif scene == Scene.STORY_SKIP:
self.tap_element("story_skip_confirm_dialog", x_rate=0.94)
else:
NavigationSolver().run(self.level_name, mode="copy")

View file

@ -10,8 +10,7 @@ from typing import Literal
from mower.data import agent_list, base_room_list
from mower.solvers.credit import CreditSolver
from mower.solvers.credit_fight import CreditFight
# from mower.solvers.cultivate_depot import cultivate as cultivateDepotSolver
from mower.solvers.cultivate_depot import cultivate as cultivateDepotSolver
from mower.solvers.depotREC import depotREC as DepotSolver
from mower.solvers.infra.base_mixin import BaseMixin
from mower.solvers.infra.clue import ClueSolver
@ -587,7 +586,7 @@ class BaseSchedulerSolver(SceneGraphSolver, BaseMixin):
def infra_main(self):
"""位于基建首页"""
if self.find("control_central") is None:
if config.recog.match2d("control_central")[0] < 0.9:
self.back()
return
if self.task is not None:
@ -2872,8 +2871,8 @@ class BaseSchedulerSolver(SceneGraphSolver, BaseMixin):
def 仓库扫描(self):
try:
# cultivateDepotSolver().start()
DepotSolver().run()
cultivateDepotSolver().start()
except Exception as e:
logger.exception(f"先不运行 出bug了 : {e}")
return False

View file

@ -0,0 +1,16 @@
from .battle_agent_choose import BattleAgentChooseSolver
from .choose_squad import ChooseSquadSolver
class BattleChooseSolver:
def run(self, level_name: str, opers: list, groups: list = None, squad: int = None):
"""
Args:
level_name: 关卡名
opers: 干员列表
groups: 干员组列表
squad: 队伍编号
"""
if squad:
ChooseSquadSolver().run(level_name, squad)
BattleAgentChooseSolver().run(opers, groups)

View file

@ -1,26 +1,23 @@
import math
from copy import deepcopy
from tkinter.tix import Tree
import cv2
from matplotlib import pyplot as plt
from mower.data import agent_list
from mower.utils import config
from mower.utils.character_recognize import (
match_portrait,
operator_team,
operator_team_select,
)
from mower.utils.config import conf
from mower.utils.graph.utils import SceneGraphSolver
from mower.utils.image import cropimg
from mower.utils.log import logger
from mower.utils.scene import Scene
from .choose_skill import ChooseSkillSolver
class Battle_ChooseSolver(SceneGraphSolver):
def run(self, agents: list) -> None:
class BattleAgentChooseSolver(SceneGraphSolver):
def run(self, agents: list, groups: list = None) -> None:
if agents == []:
raise ValueError("干员列表为空")
self.agents = agents
@ -52,7 +49,7 @@ class Battle_ChooseSolver(SceneGraphSolver):
if self.agent is None:
self.agent = self.agents_copy.pop(0)
elif self.agent["name"] in now_choose.keys():
self.check_skill()
ChooseSkillSolver().run(self.agent["skill"])
self.tag_choosed()
try:
self.agent = self.agents_copy.pop(0)
@ -114,13 +111,6 @@ class Battle_ChooseSolver(SceneGraphSolver):
logger.debug(f"segments:{segments}")
return dict(match_portrait(config.recog.gray, segment=segments))
def check_skill(self):
plt.imshow(config.recog.img)
plt.show()
self.swipe_noinertia((300, 800), (0, -500), interval=0.5)
pass
def tag_choosed(self, profession: str = "ALL"):
str = "choose_agent/profession/" + profession
if pos := self.find(str):
@ -143,6 +133,9 @@ class Battle_ChooseSolver(SceneGraphSolver):
def transition(self) -> bool:
if (scene := self.scene()) == Scene.OPERATOR_AGENT_SELECT:
return self.choose_agents()
elif scene == Scene.OPERATOR_SELECT:
self.tap_element("choose_agent/fast_select")
elif scene in self.waiting_scene:
self.waiting_solver()
else:
return False

View file

@ -0,0 +1,59 @@
import cv2
from scipy.signal import argrelmax
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cmatch, cropimg, loadres
from mower.utils.log import logger
from mower.utils.recognize import Scene
class ChooseSkillSolver(SceneGraphSolver):
"选择干员技能"
def run(self, skill: int):
logger.info(f"选择{skill}技能")
self.skill = skill
self.reverse = False
super().run()
def match_light(self):
"找闪电确定技能位置"
x = 88
img = cropimg(config.recog.img, ((x, 600), (112, 1080)))
threshold = 0.7
res = loadres("fight/light")
result = cv2.matchTemplate(img, res, cv2.TM_CCOEFF_NORMED).T[0]
print(result)
pos_list = []
for i in argrelmax(result, order=50)[0]:
if result[i] > threshold:
pos_list.append((x, i + 600))
logger.debug(pos_list)
return pos_list
def skill_be_choosen(self, y) -> bool:
"技能是否被选择"
img = cropimg(config.recog.img, ((539, y), (544, y + 5)))
res = loadres("fight/skill_be_choosen")
return cmatch(img, res, 70)
def transition(self):
if (scene := self.scene()) == Scene.OPERATOR_AGENT_SELECT:
if self.skill > len(pos_list := self.match_light()) and not self.reverse:
self.swipe_noinertia((300, 800), (0, -500), interval=0.5)
self.reverse = True
self.sleep(0.5)
elif self.reverse:
if self.skill_be_choosen(pos_list[-1][1]):
return True
else:
self.tap(pos_list[-1])
elif self.skill_be_choosen(pos_list[self.skill - 1][1]):
return True
else:
self.tap(pos_list[self.skill - 1])
elif scene in self.waiting_scene:
self.waiting_solver()
else:
return

View file

@ -0,0 +1,39 @@
import cv2
from mower.solvers.navigation import NavigationSolver
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg
from mower.utils.log import logger
from mower.utils.recognize import Scene
class ChooseSquadSolver(SceneGraphSolver):
"选择编队"
def run(self, level_name, squad: int):
logger.info("Start: 选择编队")
self.level_name = level_name
self.squad = squad
super().run()
def current_squad(self):
count = []
for i in range(4):
hsv = cropimg(
config.recog.hsv, ((153 + i * 411, 990), (550 + i * 411, (1080)))
)
mask = cv2.inRange(hsv, (97, 0, 0), (101, 255, 255))
count.append(cv2.countNonZero(mask))
return count.index(max(count)) + 1
def transition(self):
if (scene := self.scene()) == Scene.OPERATOR_SELECT:
if self.current_squad() != self.squad:
self.tap((self.squad * 411 - 99, 1040))
else:
return True
elif scene in self.waiting_scene:
self.waiting_solver()
else:
NavigationSolver().run(self.level_name, mode="copy")

View file

@ -21,7 +21,7 @@ class CreditFight(SceneGraphSolver):
logger.info("Start: 信用作战")
self.support = False
navi_solver = NavigationSolver()
navi_solver.run("OF-1")
navi_solver.run("OF-1", mode="copy")
super().run()
def choose_support(self):
@ -48,16 +48,7 @@ class CreditFight(SceneGraphSolver):
return count.index(max(count)) + 1
def transition(self):
if (scene := self.scene()) == Scene.OPERATOR_BEFORE:
if config.recog.gray[65][1333] < 200:
self.sleep()
return
# 取消代理作战
if config.recog.gray[907][1600] > 127:
self.tap((1776, 908))
return
self.tap_element("ope_start", interval=2)
elif scene == Scene.OPERATOR_SELECT:
if (scene := self.scene()) == Scene.OPERATOR_SELECT:
if self.find("ope_select_start_empty"):
logger.info("编队内没有编入干员,停止OF-1")
return True
@ -91,7 +82,7 @@ class CreditFight(SceneGraphSolver):
elif scene == Scene.OPERATOR_SUPPORT:
self.tap(self.choose_support())
self.support = True
elif scene == Scene.OPERATOR_STRANGER_SUPPORT:
elif scene == Scene.OPERATOR_SUPPORT_AGENT:
self.tap_element("fight/use")
elif scene == Scene.OPERATOR_FINISH:
return True
@ -104,4 +95,4 @@ class CreditFight(SceneGraphSolver):
self.waiting_solver()
else:
navi_solver = NavigationSolver()
navi_solver.run("OF-1")
navi_solver.run("OF-1", mode="copy")

View file

@ -1,166 +1,48 @@
import hashlib
import hmac
import json
import time
from urllib import parse
import requests
from mower.solvers.depot_reader import DepotManager
from mower.utils import config
from mower.utils.log import logger
from mower.utils.path import get_path
app_code = "4ca99fa6b56cc2ba"
# 签到url
sign_url = "https://zonai.skland.com/api/v1/game/attendance"
# 绑定的角色url
binding_url = "https://zonai.skland.com/api/v1/game/player/binding"
# 验证码url
login_code_url = "https://as.hypergryph.com/general/v1/send_phone_code"
# 验证码登录
token_phone_code_url = "https://as.hypergryph.com/user/auth/v2/token_by_phone_code"
# 密码登录
token_password_url = "https://as.hypergryph.com/user/auth/v1/token_by_phone_password"
# 使用token获得认证代码
grant_code_url = "https://as.hypergryph.com/user/oauth2/v2/grant"
# 使用认证代码获得cred
cred_code_url = "https://zonai.skland.com/api/v1/user/auth/generate_cred_by_code"
from mower.utils.skland import (
get_binding_list,
get_cred_by_token,
get_sign_header,
header,
log,
)
class cultivate:
def __init__(self):
self.record_path = get_path("@app/tmp/cultivate.json")
self.header = {
"cred": "",
"User-Agent": "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0",
"Accept-Encoding": "gzip",
"Connection": "close",
}
self.header_login = {
"User-Agent": "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0",
"Accept-Encoding": "gzip",
"Connection": "close",
}
self.reward = []
self.header_for_sign = {"platform": "", "timestamp": "", "dId": "", "vName": ""}
self.sign_token = ""
self.all_recorded = True
def start(self):
for item in config.conf.skland_info:
if item.isCheck:
self.save_param(self.get_cred_by_token(self.log(item)))
for i in self.get_binding_list():
self.save_param(get_cred_by_token(log(item)))
for i in get_binding_list(self.sign_token):
if item.cultivate_select == i.get("isOfficial"):
body = {"gameId": 1, "uid": i.get("uid")}
ingame = f"https://zonai.skland.com/api/v1/game/cultivate/player?uid={i.get('uid')}"
resp = requests.get(
ingame,
headers=self.get_sign_header(
ingame, "get", body, self.header
headers=get_sign_header(
ingame, "get", body, self.sign_token
),
).json()
with open(self.record_path, "w", encoding="utf-8") as file:
json.dump(resp, file, ensure_ascii=False, indent=4)
if resp["message"] == "OK":
depot_manager = DepotManager()
depot_manager.森空岛导入(
resp["data"]["items"], resp["timestamp"]
)
def save_param(self, cred_resp):
self.header["cred"] = cred_resp["cred"]
header["cred"] = cred_resp["cred"]
self.sign_token = cred_resp["token"]
def log(self, account):
r = requests.post(
token_password_url,
json={"phone": account.account, "password": account.password},
headers=self.header_login,
).json()
if r.get("status") != 0:
raise Exception(f'获得token失败{r["msg"]}')
return r["data"]["token"]
def get_cred_by_token(self, token):
return self.get_cred(self.get_grant_code(token))
def get_grant_code(self, token):
response = requests.post(
grant_code_url,
json={"appCode": app_code, "token": token, "type": 0},
headers=self.header_login,
)
resp = response.json()
if response.status_code != 200:
raise Exception(f"获得认证代码失败:{resp}")
if resp.get("status") != 0:
raise Exception(f'获得认证代码失败:{resp["msg"]}')
return resp["data"]["code"]
def get_cred(self, grant):
resp = requests.post(
cred_code_url, json={"code": grant, "kind": 1}, headers=self.header_login
).json()
if resp["code"] != 0:
raise Exception(f'获得cred失败{resp["message"]}')
return resp["data"]
def get_binding_list(self):
v = []
resp = requests.get(
binding_url,
headers=self.get_sign_header(binding_url, "get", None, self.header),
).json()
if resp["code"] != 0:
logger.warning(f"请求角色列表出现问题:{resp['message']}")
if resp.get("message") == "用户未登录":
logger.warning("用户登录可能失效了,请重新运行此程序!")
return []
for i in resp["data"]["list"]:
if i.get("appCode") != "arknights":
continue
v.extend(i.get("bindingList"))
return v
def get_sign_header(self, url: str, method, body, old_header):
h = json.loads(json.dumps(old_header))
p = parse.urlparse(url)
if method.lower() == "get":
h["sign"], header_ca = self.generate_signature(
self.sign_token, p.path, p.query
)
else:
h["sign"], header_ca = self.generate_signature(
self.sign_token, p.path, json.dumps(body)
)
for i in header_ca:
h[i] = header_ca[i]
return h
def generate_signature(self, token: str, path, body_or_query):
"""
获得签名头
接口地址+方法为Get请求用query否则用body+时间戳+ 请求头的四个重要参数dIdplatformtimestampvName.toJSON()
将此字符串做HMAC加密算法为SHA-256密钥token为请求cred接口会返回的一个token值
再将加密后的字符串做MD5即得到sign
:param token: 拿cred时候的token
:param path: 请求路径不包括网址
:param body_or_query: 如果是GET则是它的queryPOST则为它的body
:return: 计算完毕的sign
"""
# 总是说请勿修改设备时间怕不是yj你的服务器有问题吧所以这里特地-2
t = str(int(time.time()) - 2)
token = token.encode("utf-8")
header_ca = json.loads(json.dumps(self.header_for_sign))
header_ca["timestamp"] = t
header_ca_str = json.dumps(header_ca, separators=(",", ":"))
s = path + body_or_query + t + header_ca_str
hex_s = hmac.new(token, s.encode("utf-8"), hashlib.sha256).hexdigest()
md5 = (
hashlib.md5(hex_s.encode("utf-8"))
.hexdigest()
.encode("utf-8")
.decode("utf-8")
)
return md5, header_ca

View file

@ -1,4 +1,3 @@
import json
import lzma
import os
import pickle
@ -7,16 +6,15 @@ from datetime import datetime
import cv2
import numpy as np
import pandas as pd
from skimage.feature import hog
from sklearn.cluster import KMeans
from mower import __rootdir__
from mower.solvers.depot_reader import DepotManager
from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import loadimg
from mower.utils.log import logger
from mower.utils.path import get_path
from mower.utils.recognize import Scene
# 向下x变大 = 0
@ -73,8 +71,11 @@ def 拼图(图片列表):
else:
logger.warning(f"仓库扫描: 拼接失败,状态码: {status}")
raise RuntimeError(f"拼接失败,状态码: {status}")
except RuntimeError as e:
logger.error(f"仓库扫描: 拼接过程中出现错误: {e}")
except cv2.error as e:
logger.error(f"OpenCV 错误: {e}")
raise
except Exception as e:
logger.error(f"拼接过程中出现错误: {e}")
raise
@ -158,16 +159,10 @@ class depotREC(SceneGraphSolver):
def __init__(self) -> None:
start_time = datetime.now()
# sift = cv2.SIFT_create()
orb = cv2.ORB_create()
bf = cv2.BFMatcher(cv2.NORM_HAMMING2, crossCheck=True)
# flann = cv2.FlannBasedMatcher(
# dict(algorithm=1, trees=2), dict(checks=50))
self.detector = orb
self.matcher = bf
self.仓库输出 = get_path("@app/tmp/depotresult.csv")
with lzma.open(f"{__rootdir__}/models/CONSUME.pkl", "rb") as pkl:
self.knn模型_CONSUME = pickle.load(pkl)
with lzma.open(f"{__rootdir__}/models/MATERIAL.pkl", "rb") as pkl:
@ -258,15 +253,10 @@ class depotREC(SceneGraphSolver):
else:
logger.info("仓库扫描: 这个分类下没有物品")
logger.info(f"仓库扫描: {self.结果字典}")
result = [
int(datetime.now().timestamp()),
json.dumps(self.结果字典, ensure_ascii=False),
{"森空岛输出仅占位": ""},
]
depotinfo = pd.DataFrame([result], columns=["Timestamp", "Data", "json"])
depotinfo.to_csv(
self.仓库输出, mode="a", index=False, header=False, encoding="utf-8"
)
depot_manager = DepotManager()
depot_manager.CV导入(self.结果字典, int(datetime.now().timestamp()))
else:
self.back_to_index()
return True
@ -291,7 +281,9 @@ class depotREC(SceneGraphSolver):
logger.info(f"仓库扫描: 把第{len(截图列表)}页保存进内存中等待识别")
if "养成材料" in 分类名称:
while True:
self.swipe_noinertia((1800, 450), (-1000, 0)) # 滑动
self.swipe_noinertia(
(1800, 450), (-1000, 0), interval=2
) # 滑动 等待两秒 省的比较不出来
config.recog.update()
新的截图 = config.recog.img
新的截图 = 新的截图[140:1000, :]

View file

@ -0,0 +1,289 @@
from datetime import datetime
from sqlalchemy import Column, ForeignKey, Integer, String, Text, create_engine
from sqlalchemy.orm import declarative_base, relationship, sessionmaker
from mower.data import key_mapping
from mower.utils.path import get_path
Base = declarative_base()
class Item(Base):
__tablename__ = "items"
itemId = Column(String, primary_key=True)
counts = relationship("Count", back_populates="item")
class Count(Base):
__tablename__ = "counts"
id = Column(Integer, primary_key=True, autoincrement=True)
itemId = Column(String, ForeignKey("items.itemId"))
count = Column(Text)
time = Column(Text)
type = Column(String)
item = relationship("Item", back_populates="counts")
class Translation(Base):
__tablename__ = "translations"
itemId = Column(String, ForeignKey("items.itemId"), primary_key=True)
iconId = Column(String)
name = Column(String)
classifyType = Column(String)
sortId = Column(Integer)
category = Column(String, default="K未分类")
item = relationship("Item", uselist=False)
sort = {
"A常用": [
"至纯源石",
"合成玉",
"寻访凭证",
"十连寻访凭证",
"龙门币",
"高级凭证",
"资质凭证",
"招聘许可",
],
"B经验卡": ["基础作战记录", "初级作战记录", "中级作战记录", "高级作战记录"],
"C稀有度5": ["烧结核凝晶", "晶体电子单元", "D32钢", "双极纳米片", "聚合剂"],
"D稀有度4": [
"提纯源岩",
"改量装置",
"聚酸酯块",
"糖聚块",
"异铁块",
"酮阵列",
"转质盐聚块",
"切削原液",
"精炼溶剂",
"晶体电路",
"炽合金块",
"聚合凝胶",
"白马醇",
"三水锰矿",
"五水研磨石",
"RMA70-24",
"环烃预制体",
"固化纤维板",
],
"E稀有度3": [
"固源岩组",
"全新装置",
"聚酸酯组",
"糖组",
"异铁组",
"酮凝集组",
"转质盐组",
"化合切削液",
"半自然溶剂",
"晶体元件",
"炽合金",
"凝胶",
"扭转醇",
"轻锰矿",
"研磨石",
"RMA70-12",
"环烃聚质",
"褐素纤维",
],
"F稀有度2": ["固源岩", "装置", "聚酸酯", "", "异铁", "酮凝集"],
"G稀有度1": ["源岩", "破损装置", "酯原料", "代糖", "异铁碎片", "双酮"],
"H模组": ["模组数据块", "数据增补仪", "数据增补条"],
"I技能书": ["技巧概要·卷3", "技巧概要·卷2", "技巧概要·卷1"],
"J芯片相关": [
"重装双芯片",
"重装芯片组",
"重装芯片",
"狙击双芯片",
"狙击芯片组",
"狙击芯片",
"医疗双芯片",
"医疗芯片组",
"医疗芯片",
"术师双芯片",
"术师芯片组",
"术师芯片",
"先锋双芯片",
"先锋芯片组",
"先锋芯片",
"近卫双芯片",
"近卫芯片组",
"近卫芯片",
"辅助双芯片",
"辅助芯片组",
"辅助芯片",
"特种双芯片",
"特种芯片组",
"特种芯片",
"采购凭证",
"芯片助剂",
],
"K未分类": [],
}
class DepotManager:
def __init__(self):
self.sort = sort
self.read_time = 0
self.path = get_path("@app/tmp/depot_data.db")
self.engine = create_engine(f"sqlite:///{self.path}", echo=True)
Base.metadata.create_all(self.engine)
self.Session = sessionmaker(bind=self.engine)
self.insert_translations()
def insert_translations(self):
with self.Session() as session:
for itemId, translation in key_mapping.items():
iconId, name, classifyType, sortId = (
translation[1],
translation[2],
translation[3],
translation[4],
)
translation_obj = (
session.query(Translation).filter_by(itemId=itemId).first()
)
if not translation_obj:
translation_obj = Translation(
itemId=itemId,
iconId=iconId,
name=name,
classifyType=classifyType,
sortId=sortId,
category="K未分类",
)
session.add(translation_obj)
for category, items in self.sort.items():
for name in items:
session.query(Translation).filter_by(name=name).update(
{Translation.category: category}
)
session.commit()
def 森空岛导入(self, items, time):
with self.Session() as session: # 使用上下文管理器
for item in items:
itemId = item["id"]
if not session.query(Item).filter_by(itemId=itemId).first():
session.add(Item(itemId=itemId))
session.merge(
Count(itemId=itemId, count=item["count"], time=time, type="SK")
)
session.commit()
def CV导入(self, items, time):
with self.Session() as session: # 使用上下文管理器
for name, count in items.items():
result = session.query(Translation).filter_by(name=name).first()
if result:
itemId = result.itemId
session.merge(
Count(itemId=itemId, count=count, time=time, type="CV")
)
else:
print(f"Item with name '{name}' not found in translations.")
session.commit()
def 读取仓库(self):
def _add_custom_fields(classified_data):
classified_data["B经验卡"]["全部经验(计算)"] = {
"number": (
classified_data["B经验卡"]["基础作战记录"]["number"] * 200
+ classified_data["B经验卡"]["初级作战记录"]["number"] * 400
+ classified_data["B经验卡"]["中级作战记录"]["number"] * 1000
+ classified_data["B经验卡"]["高级作战记录"]["number"] * 2000
),
"sort": 9999999,
"icon": "EXP",
}
合成玉数量 = classified_data["A常用"].get("合成玉", {"number": 0})["number"]
寻访凭证数量 = (
classified_data["A常用"].get("寻访凭证", {"number": 0})["number"]
+ classified_data["A常用"].get("十连寻访凭证", {"number": 0})["number"]
* 10
)
源石数量 = classified_data["A常用"].get("至纯源石", {"number": 0})["number"]
源石碎片 = classified_data["K未分类"].get("源石碎片", {"number": 0})[
"number"
]
classified_data["A常用"]["玉+卷"] = {
"number": round(合成玉数量 / 600 + 寻访凭证数量, 1),
"sort": 9999999,
"icon": "寻访凭证",
}
classified_data["A常用"]["玉+卷+石"] = {
"number": round((合成玉数量 + 源石数量 * 180) / 600 + 寻访凭证数量, 1),
"sort": 9999999,
"icon": "寻访凭证",
}
classified_data["A常用"]["额外+碎片"] = {
"number": round(
(合成玉数量 + 源石数量 * 180 + int(源石碎片 / 2) * 20) / 600
+ 寻访凭证数量,
1,
),
"sort": 9999999,
"icon": "寻访凭证",
}
return classified_data
def get_latest_counts_as_json():
with self.Session() as session: # 使用上下文管理器
# 你的读取逻辑
counts = (
session.query(Translation, Count)
.outerjoin(Count, Translation.itemId == Count.itemId)
.all()
)
result = {}
for translation, count in counts:
category = translation.category
if category not in result:
result[category] = {}
if not count or count.count is None:
latest_count = 0
else:
latest_count = int(count.count)
self.read_time = (
int(count.time) if count.time else self.read_time
)
if category == "K未分类" and latest_count == 0:
continue
result[category][translation.name] = {
"number": latest_count,
"sort": translation.sortId,
"icon": translation.name,
}
print(result)
return _add_custom_fields(result)
classified_data = get_latest_counts_as_json()
return [
classified_data,
"",
str(datetime.fromtimestamp(int(self.read_time))),
self.read_time,
]
def close_engine(self):
self.engine.dispose()
def __del__(self):
self.close_engine()

View file

@ -178,8 +178,8 @@ class EnterRoomSolver(SceneGraphSolver):
facility_top_left = va(top_left, sm(width, position))
scope = facility_top_left, va(facility_top_left, sm(width, size))
result[name] = (
(round(max(scope[0][0], 0)), round(scope[0][1])),
(round(min(scope[1][0], 1920)), round(scope[1][1])),
(max(scope[0][0], 0), scope[0][1]),
(min(scope[1][0], 1920), scope[1][1]),
)
logger.debug(result)
@ -187,8 +187,9 @@ class EnterRoomSolver(SceneGraphSolver):
def transition(self) -> bool:
if (scene := self.scene()) == Scene.INFRA_MAIN:
if pos := self.find("control_central"):
pos = self.segment(self.find("control_central"))[self.room]
score, scope = config.recog.match2d("control_central")
if score >= 0.9:
pos = self.segment(scope)[self.room]
self.ctap(pos, 1, config.screenshot_avg / 1000)
self.wait_start()
else:

View file

@ -59,7 +59,7 @@ class GetOrderRemainingTimeSolver(SceneGraphSolver, BaseMixin):
return value
def read_remain_time(self, pos) -> int:
h, m, s = self.number(pos, 19, 90).split("::")
h, m, s = self.number(pos, 19, 115).split("::")
return int(h) * 3600 + int(m) * 60 + int(s)
def timeout(self) -> bool:

View file

@ -1,8 +1,9 @@
import datetime
import os
import cv2
import pandas as pd
from sqlalchemy import Column, Date, Integer, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from mower.models import noto_sans
from mower.utils import config
@ -14,26 +15,30 @@ from mower.utils.log import logger
from mower.utils.path import get_path
from mower.utils.recognize import Scene, tp
Base = declarative_base()
def remove_blank(target: str):
if target is None or target == "":
return target
target.strip()
target.replace(" ", "")
target.replace("\u3000", "")
return target
# Database model for reports
class Report(Base):
__tablename__ = "reports"
id = Column(Integer, primary_key=True, autoincrement=True)
date = Column(Date, nullable=False, unique=True)
作战录像 = Column(Integer)
赤金 = Column(Integer)
龙门币订单 = Column(Integer)
龙门币订单数 = Column(Integer)
合成玉 = Column(Integer)
合成玉订单数量 = Column(Integer)
class ReportSolver(SceneGraphSolver):
def __init__(self) -> None:
super().__init__()
self.record_path = get_path("@app/tmp/report.csv")
self.db_path = get_path("@app/tmp/report.db")
self.low_range_gray = (100, 100, 100)
self.high_range_gray = (255, 255, 255)
self.date = (
(datetime.datetime.now() - datetime.timedelta(hours=4)).date().__str__()
)
self.date = (datetime.datetime.now() - datetime.timedelta(hours=4)).date()
self.digitReader = DigitReader()
self.report_res = {
"作战录像": None,
@ -45,6 +50,12 @@ class ReportSolver(SceneGraphSolver):
}
self.reload_time = 0
# Setup SQLAlchemy with dynamic DATABASE_URL
self.DATABASE_URL = f"sqlite:///{self.db_path}" # Dynamic DB URL
self.engine = create_engine(self.DATABASE_URL)
Base.metadata.create_all(self.engine)
self.Session = sessionmaker(bind=self.engine)
def run(self):
if self.has_record():
logger.info("今天的基报看过了")
@ -60,7 +71,6 @@ class ReportSolver(SceneGraphSolver):
def transition(self) -> bool:
if self.scene() == Scene.RIIC_REPORT:
return self.read_report()
else:
self.scene_graph_step(Scene.RIIC_REPORT)
@ -79,18 +89,23 @@ class ReportSolver(SceneGraphSolver):
return True
self.reload_time += 1
self.sleep(1)
return
def record_report(self):
logger.info(f"存入{self.date}的数据{self.report_res}")
try:
res_df = pd.DataFrame(self.report_res, index=[self.date])
res_df.to_csv(
self.record_path,
mode="a",
header=not os.path.exists(self.record_path),
encoding="gbk",
)
with self.Session() as session:
report = Report(
date=self.date,
作战录像=self.report_res["作战录像"],
赤金=self.report_res["赤金"],
龙门币订单=self.report_res["龙门币订单"],
龙门币订单数=self.report_res["龙门币订单数"],
合成玉=self.report_res["合成玉"],
合成玉订单数量=self.report_res["合成玉订单数量"],
)
session.merge(report)
session.commit()
except Exception as e:
logger.exception(f"存入数据失败:{e}")
self.tap((1253, 81), interval=2)
@ -109,17 +124,11 @@ class ReportSolver(SceneGraphSolver):
def has_record(self):
try:
if os.path.exists(self.record_path) is False:
logger.debug("基报不存在")
return False
df = pd.read_csv(self.record_path, encoding="gbk", on_bad_lines="skip")
for item in df.iloc:
if item[0] == self.date:
return True
return False
except PermissionError:
logger.info("report.csv正在被占用")
except pd.errors.EmptyDataError:
with self.Session() as session: # 使用上下文管理器
record_exists = session.query(Report).filter_by(date=self.date).first()
return record_exists is not None
except Exception as e:
logger.exception(f"查询数据库失败:{e}")
return False
def crop_report(self):
@ -194,16 +203,129 @@ class ReportSolver(SceneGraphSolver):
return value
def get_report_data(self):
# 连接数据库
try:
with self.Session() as session:
format_data = []
def get_report_data():
record_path = get_path("@app/tmp/report.csv")
try:
data = {}
if os.path.exists(record_path) is False:
logger.debug("基报不存在")
return False
df = pd.read_csv(record_path, encoding="gbk")
data = df.to_dict("dict")
print(data)
except PermissionError:
logger.info("report.csv正在被占用")
# 查询所有报告数据
records = session.query(Report).all()
# 将记录转化为所需格式
for record in records:
format_data.append(
{
"日期": record.date.strftime(
"%Y-%m-%d"
), # 日期格式化为字符串
"作战录像": record.作战录像,
"赤金": record.赤金,
"制造总数": int(record.赤金 + record.作战录像),
"龙门币订单": record.龙门币订单,
"反向作战录像": -record.作战录像,
"龙门币订单数": record.龙门币订单数,
"每单获取龙门币": int(
record.龙门币订单 / record.龙门币订单数
)
if record.龙门币订单数
else 0,
}
)
# 如果格式化后的数据少于15条则添加缺失的日期
earliest_date = (
min(record.date for record in records)
if records
else datetime.date.today()
)
if len(format_data) < 15:
for i in range(1, 16 - len(format_data)):
format_data.insert(
0,
{
"日期": (
earliest_date - datetime.timedelta(days=i + 1)
).strftime("%Y-%m-%d"),
"作战录像": "-",
"赤金": "-",
"龙门币订单": "-",
"龙门币订单数": "-",
"每单获取龙门币": "-",
},
)
logger.debug(format_data)
return format_data
except Exception as e:
logger.exception(f"读取数据库失败: {e}")
def get_orundum_data(self):
try:
format_data = []
with self.Session() as session:
# 查询所有报告数据
records = session.query(Report).all()
earliest_date = datetime.datetime.now()
# 初始化制造合成玉的开始日期
begin_make_orundum = (earliest_date + datetime.timedelta(days=1)).date()
if len(records) >= 15:
for i in range(len(records) - 1, -1, -1):
record = records[i]
if 0 < i < len(records) - 15:
continue
if record.合成玉 > 0:
begin_make_orundum = record.date
else:
for record in records:
if record.合成玉 > 0:
begin_make_orundum = record.date
if begin_make_orundum > earliest_date.date():
return format_data
total_orundum = 0
for record in records:
total_orundum += record.合成玉
format_data.append(
{
"日期": record.date.strftime("%Y-%m-%d"),
"合成玉": record.合成玉,
"合成玉订单数量": record.合成玉订单数量,
"抽数": round((record.合成玉 / 600), 1),
"累计制造合成玉": total_orundum,
}
)
if len(format_data) < 15:
earliest_date = records[0].date
for i in range(1, 16 - len(format_data)):
format_data.insert(
0,
{
"日期": (
earliest_date - datetime.timedelta(days=i + 1)
).strftime("%Y-%m-%d"),
"合成玉": "-",
"合成玉订单数量": "-",
"抽数": "-",
"累计制造合成玉": 0,
},
)
logger.debug(format_data)
return format_data
except Exception as e:
logger.exception(f"获取合成玉数据失败:{e}")
return []
def close_engine(self):
self.engine.dispose()
def __del__(self):
self.close_engine()

View file

@ -430,8 +430,12 @@ difficulty_str = [
class NavigationSolver(SceneGraphSolver):
def run(self, name: str):
if LastStageNavigation().run(name):
def run(self, name: str, mode: str = "auto"):
"""
mode:默认为auto,抄作业为copy
"""
if LastStageNavigation().run(name, mode):
return True
if name in ActivityNavigation.location:
ActivityNavigation().run(name)
@ -440,6 +444,7 @@ class NavigationSolver(SceneGraphSolver):
self.success = False
self.act = None
self.name = name
self.mode = mode
prefix = name.split("-")[0]
pr_prefix = ""
if prefix == "PR":
@ -617,22 +622,38 @@ class NavigationSolver(SceneGraphSolver):
self.success = True
self.tap(va(target, (60, 20)))
elif scene == Scene.OPERATOR_BEFORE:
if self.act == 2:
if self.change_to is not None:
logger.info(f"{self.name} 无法代理")
self.success = False
self.back_to_index()
if self.mode == "auto":
if self.act == 2:
if self.change_to is not None:
logger.info(f"{self.name} 无法代理")
self.success = False
self.back_to_index()
return True
if self.find("ope_agency_lock"):
self.change_to = self.now_difficulty ^ 1
logger.info(
f"{self.name} {difficulty_str[self.now_difficulty]} 无法代理,切难度尝试"
)
self.back()
return
if self.success:
return True
if self.find("ope_agency_lock"):
self.change_to = self.now_difficulty ^ 1
logger.info(
f"{self.name} {difficulty_str[self.now_difficulty]} 无法代理,切难度尝试"
)
else:
self.back()
elif self.mode == "copy":
if config.recog.gray[65][1333] < 200:
self.sleep()
return
if self.success:
return True
else:
self.back()
# 取消代理作战
if config.recog.gray[907][1600] > 127 and not self.find(
"ope_agency_lock"
):
self.tap((1776, 908))
return
self.tap_element("ope_start", interval=2)
elif scene == Scene.OPERATOR_SELECT and self.success:
return True
else:
self.scene_graph_step(Scene.TERMINAL_MAIN)

View file

@ -31,19 +31,20 @@ class classproperty:
class ActivityNavigation(SceneGraphSolver):
_location = {
"CV-1": (0, 0),
"CV-2": (601, -175),
"CV-3": (1181, -175),
"CV-4": (1757, -175),
"CV-5": (2344, -61),
"CV-6": (2755, 55),
"CV-7": (3208, -87),
"CV-8": (3617, 2),
"GO-1": (0, 0),
"GO-2": (996, 0),
"GO-3": (1464, 0),
"GO-4": (1461, -341),
"GO-5": (2088, -341),
"GO-6": (2088, 126),
"GO-7": (2659, 126),
"GO-8": (2967, -340),
"GO-9": (3312, -105),
}
@classproperty
def location(cls):
if datetime.now() > datetime(2024, 9, 29, 4):
if datetime.now() > datetime(2024, 10, 30, 4):
return {}
return cls._location

View file

@ -10,8 +10,9 @@ from .utils import last_letters
class LastStageNavigation(SceneGraphSolver):
def run(self, name: str) -> None:
def run(self, name: str, mode: str) -> None:
self.name = name
self.mode = mode
self.success = True
if self.name != "":
self.scene_graph_navigation(Scene.TERMINAL_MAIN)
@ -59,6 +60,21 @@ class LastStageNavigation(SceneGraphSolver):
self.success = False
return True
elif scene == Scene.OPERATOR_BEFORE:
if self.mode == "auto":
return True
else:
if config.recog.gray[65][1333] < 200:
self.sleep()
return
# 取消代理作战
if config.recog.gray[907][1600] > 127 and not self.find(
"ope_agency_lock"
):
self.tap((1776, 908))
return
self.tap_element("ope_start", interval=2)
elif scene == Scene.OPERATOR_SELECT and self.mode == "copy":
return True
else:
self.scene_graph_step(Scene.TERMINAL_MAIN)

View file

@ -1,10 +1,5 @@
import datetime
import hashlib
import hmac
import json
import os
import time
from urllib import parse
import pandas as pd
import requests
@ -12,45 +7,24 @@ import requests
from mower.utils import config
from mower.utils.log import logger
from mower.utils.path import get_path
app_code = "4ca99fa6b56cc2ba"
# 签到url
sign_url = "https://zonai.skland.com/api/v1/game/attendance"
# 绑定的角色url
binding_url = "https://zonai.skland.com/api/v1/game/player/binding"
# 验证码url
login_code_url = "https://as.hypergryph.com/general/v1/send_phone_code"
# 验证码登录
token_phone_code_url = "https://as.hypergryph.com/user/auth/v2/token_by_phone_code"
# 密码登录
token_password_url = "https://as.hypergryph.com/user/auth/v1/token_by_phone_password"
# 使用token获得认证代码
grant_code_url = "https://as.hypergryph.com/user/oauth2/v2/grant"
# 使用认证代码获得cred
cred_code_url = "https://zonai.skland.com/api/v1/user/auth/generate_cred_by_code"
from mower.utils.skland import (
get_binding_list,
get_cred_by_token,
get_sign_header,
header,
header_login,
log,
sign_url,
token_password_url,
)
class SKLand:
def __init__(self):
self.record_path = get_path("@app/tmp/skland.csv")
self.header = {
"cred": "",
"User-Agent": "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0",
"Accept-Encoding": "gzip",
"Connection": "close",
}
self.header_login = {
"User-Agent": "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0",
"Accept-Encoding": "gzip",
"Connection": "close",
}
self.reward = []
# 签名请求头一定要这个顺序,否则失败
# timestamp是必填的,其它三个随便填,不要为none即可
self.header_for_sign = {"platform": "", "timestamp": "", "dId": "", "vName": ""}
self.sign_token = ""
self.all_recorded = True
@ -59,13 +33,14 @@ class SKLand:
if self.has_record(item.account):
continue
self.all_recorded = False
self.save_param(self.get_cred_by_token(self.log(item)))
for i in self.get_binding_list():
self.save_param(get_cred_by_token(log(item)))
for i in get_binding_list(self.sign_token):
body = {"gameId": 1, "uid": i.get("uid")}
# list_awards(1, i.get('uid'))
resp = requests.post(
sign_url,
headers=self.get_sign_header(sign_url, "post", body, self.header),
headers=get_sign_header(
sign_url, "post", body, self.sign_token, header
),
json=body,
).json()
if resp["code"] != 0:
@ -93,104 +68,19 @@ class SKLand:
return False
def save_param(self, cred_resp):
self.header["cred"] = cred_resp["cred"]
header["cred"] = cred_resp["cred"]
self.sign_token = cred_resp["token"]
def log(self, account):
r = requests.post(
token_password_url,
json={"phone": account.account, "password": account.password},
headers=self.header_login,
headers=header_login,
).json()
if r.get("status") != 0:
raise Exception(f'获得token失败{r["msg"]}')
return r["data"]["token"]
def get_cred_by_token(self, token):
return self.get_cred(self.get_grant_code(token))
def get_grant_code(self, token):
response = requests.post(
grant_code_url,
json={"appCode": app_code, "token": token, "type": 0},
headers=self.header_login,
)
resp = response.json()
if response.status_code != 200:
raise Exception(f"获得认证代码失败:{resp}")
if resp.get("status") != 0:
raise Exception(f'获得认证代码失败:{resp["msg"]}')
return resp["data"]["code"]
def get_cred(self, grant):
resp = requests.post(
cred_code_url, json={"code": grant, "kind": 1}, headers=self.header_login
).json()
if resp["code"] != 0:
raise Exception(f'获得cred失败{resp["message"]}')
return resp["data"]
def get_binding_list(self):
v = []
resp = requests.get(
binding_url,
headers=self.get_sign_header(binding_url, "get", None, self.header),
).json()
if resp["code"] != 0:
print(f"请求角色列表出现问题:{resp['message']}")
if resp.get("message") == "用户未登录":
print("用户登录可能失效了,请重新运行此程序!")
return []
for i in resp["data"]["list"]:
if i.get("appCode") != "arknights":
continue
v.extend(i.get("bindingList"))
return v
def get_sign_header(self, url: str, method, body, old_header):
h = json.loads(json.dumps(old_header))
p = parse.urlparse(url)
if method.lower() == "get":
h["sign"], header_ca = self.generate_signature(
self.sign_token, p.path, p.query
)
else:
h["sign"], header_ca = self.generate_signature(
self.sign_token, p.path, json.dumps(body)
)
for i in header_ca:
h[i] = header_ca[i]
return h
def generate_signature(self, token: str, path, body_or_query):
"""
获得签名头
接口地址+方法为Get请求用query否则用body+时间戳+ 请求头的四个重要参数dIdplatformtimestampvName.toJSON()
将此字符串做HMAC加密算法为SHA-256密钥token为请求cred接口会返回的一个token值
再将加密后的字符串做MD5即得到sign
:param token: 拿cred时候的token
:param path: 请求路径不包括网址
:param body_or_query: 如果是GET则是它的queryPOST则为它的body
:return: 计算完毕的sign
"""
# 总是说请勿修改设备时间怕不是yj你的服务器有问题吧所以这里特地-2
t = str(int(time.time()) - 2)
token = token.encode("utf-8")
header_ca = json.loads(json.dumps(self.header_for_sign))
header_ca["timestamp"] = t
header_ca_str = json.dumps(header_ca, separators=(",", ":"))
s = path + body_or_query + t + header_ca_str
hex_s = hmac.new(token, s.encode("utf-8"), hashlib.sha256).hexdigest()
md5 = (
hashlib.md5(hex_s.encode("utf-8"))
.hexdigest()
.encode("utf-8")
.decode("utf-8")
)
return md5, header_ca
def record_log(self):
date_str = datetime.datetime.now().strftime("%Y/%m/%d")
logger.info(f"存入{date_str}的数据{self.reward}")
@ -227,8 +117,8 @@ class SKLand:
for item in config.conf.skland_info:
if item.isCheck:
try:
self.save_param(self.get_cred_by_token(self.log(item)))
for i in self.get_binding_list():
self.save_param(get_cred_by_token(log(item)))
for i in get_binding_list(self.sign_token):
if i["uid"]:
res.append(
"{}连接成功".format(

318
mower/utils/SecuritySm.py Normal file
View file

@ -0,0 +1,318 @@
# from https://gitee.com/FancyCabbage/skyland-auto-sign
import base64
import gzip
import hashlib
# 数美加密方法类
import json
import time
import uuid
import requests
from cryptography.hazmat.decrepit.ciphers.algorithms import TripleDES
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives.ciphers.algorithms import AES
from cryptography.hazmat.primitives.ciphers.base import Cipher
from cryptography.hazmat.primitives.ciphers.modes import CBC, ECB
# 查询dId请求头
devices_info_url = "https://fp-it.portal101.cn/deviceprofile/v4"
# 数美配置
SM_CONFIG = {
"organization": "UWXspnCCJN4sfYlNfqps",
"appId": "default",
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmxMNr7n8ZeT0tE1R9j/mPixoinPkeM+k4VGIn/s0k7N5rJAfnZ0eMER+QhwFvshzo0LNmeUkpR8uIlU/GEVr8mN28sKmwd2gpygqj0ePnBmOW4v0ZVwbSYK+izkhVFk2V/doLoMbWy6b+UnA8mkjvg0iYWRByfRsK2gdl7llqCwIDAQAB",
"protocol": "https",
"apiHost": "fp-it.portal101.cn",
}
PK = serialization.load_der_public_key(base64.b64decode(SM_CONFIG["publicKey"]))
DES_RULE = {
"appId": {
"cipher": "DES",
"is_encrypt": 1,
"key": "uy7mzc4h",
"obfuscated_name": "xx",
},
"box": {"is_encrypt": 0, "obfuscated_name": "jf"},
"canvas": {
"cipher": "DES",
"is_encrypt": 1,
"key": "snrn887t",
"obfuscated_name": "yk",
},
"clientSize": {
"cipher": "DES",
"is_encrypt": 1,
"key": "cpmjjgsu",
"obfuscated_name": "zx",
},
"organization": {
"cipher": "DES",
"is_encrypt": 1,
"key": "78moqjfc",
"obfuscated_name": "dp",
},
"os": {
"cipher": "DES",
"is_encrypt": 1,
"key": "je6vk6t4",
"obfuscated_name": "pj",
},
"platform": {
"cipher": "DES",
"is_encrypt": 1,
"key": "pakxhcd2",
"obfuscated_name": "gm",
},
"plugins": {
"cipher": "DES",
"is_encrypt": 1,
"key": "v51m3pzl",
"obfuscated_name": "kq",
},
"pmf": {
"cipher": "DES",
"is_encrypt": 1,
"key": "2mdeslu3",
"obfuscated_name": "vw",
},
"protocol": {"is_encrypt": 0, "obfuscated_name": "protocol"},
"referer": {
"cipher": "DES",
"is_encrypt": 1,
"key": "y7bmrjlc",
"obfuscated_name": "ab",
},
"res": {
"cipher": "DES",
"is_encrypt": 1,
"key": "whxqm2a7",
"obfuscated_name": "hf",
},
"rtype": {
"cipher": "DES",
"is_encrypt": 1,
"key": "x8o2h2bl",
"obfuscated_name": "lo",
},
"sdkver": {
"cipher": "DES",
"is_encrypt": 1,
"key": "9q3dcxp2",
"obfuscated_name": "sc",
},
"status": {
"cipher": "DES",
"is_encrypt": 1,
"key": "2jbrxxw4",
"obfuscated_name": "an",
},
"subVersion": {
"cipher": "DES",
"is_encrypt": 1,
"key": "eo3i2puh",
"obfuscated_name": "ns",
},
"svm": {
"cipher": "DES",
"is_encrypt": 1,
"key": "fzj3kaeh",
"obfuscated_name": "qr",
},
"time": {
"cipher": "DES",
"is_encrypt": 1,
"key": "q2t3odsk",
"obfuscated_name": "nb",
},
"timezone": {
"cipher": "DES",
"is_encrypt": 1,
"key": "1uv05lj5",
"obfuscated_name": "as",
},
"tn": {
"cipher": "DES",
"is_encrypt": 1,
"key": "x9nzj1bp",
"obfuscated_name": "py",
},
"trees": {
"cipher": "DES",
"is_encrypt": 1,
"key": "acfs0xo4",
"obfuscated_name": "pi",
},
"ua": {
"cipher": "DES",
"is_encrypt": 1,
"key": "k92crp1t",
"obfuscated_name": "bj",
},
"url": {
"cipher": "DES",
"is_encrypt": 1,
"key": "y95hjkoo",
"obfuscated_name": "cf",
},
"version": {"is_encrypt": 0, "obfuscated_name": "version"},
"vpw": {
"cipher": "DES",
"is_encrypt": 1,
"key": "r9924ab5",
"obfuscated_name": "ca",
},
}
BROWSER_ENV = {
"plugins": "MicrosoftEdgePDFPluginPortableDocumentFormatinternal-pdf-viewer1,MicrosoftEdgePDFViewermhjfbmdgcfjbbpaeojofohoefgiehjai1",
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0",
"canvas": "259ffe69", # 基于浏览器的canvas获得的值不知道复用行不行
"timezone": -480, # 时区,应该是固定值吧
"platform": "Win32",
"url": "https://www.skland.com/", # 固定值
"referer": "",
"res": "1920_1080_24_1.25", # 屏幕宽度_高度_色深_window.devicePixelRatio
"clientSize": "0_0_1080_1920_1920_1080_1920_1080",
"status": "0011", # 不知道在干啥
}
# // 将浏览器环境对象的key全部排序然后对其所有的值及其子对象的值加入数字并字符串相加。若值为数字则乘以10000(0x2710)再将其转成字符串存入数组,最后再做md5,存入tn变量tn变量要做加密
# //把这个对象用加密规则进行加密然后对结果做GZIP压缩结果是对象应该有序列化最后做AES加密加密细节目前不清除密钥为变量priId
# //加密规则新对象的key使用相对应加解密规则的obfuscated_name值value为字符串化后进行进行DES加密再进行btoa加密
# 通过测试
def _DES(o: dict):
result = {}
for i in o.keys():
if i in DES_RULE.keys():
rule = DES_RULE[i]
res = o[i]
if rule["is_encrypt"] == 1:
c = Cipher(TripleDES(rule["key"].encode("utf-8")), ECB())
data = str(res).encode("utf-8")
# 补足字节
data += b"\x00" * 8
res = base64.b64encode(c.encryptor().update(data)).decode("utf-8")
result[rule["obfuscated_name"]] = res
else:
result[i] = o[i]
return result
# 通过测试
def _AES(v: bytes, k: bytes):
iv = "0102030405060708"
key = AES(k)
c = Cipher(key, CBC(iv.encode("utf-8")))
c.encryptor()
# 填充明文
v += b"\x00"
while len(v) % 16 != 0:
v += b"\x00"
return c.encryptor().update(v).hex()
def GZIP(o: dict):
# 这个压缩结果似乎和前台不太一样,不清楚是否会影响
json_str = json.dumps(o, ensure_ascii=False)
stream = gzip.compress(json_str.encode("utf-8"), 2, mtime=0)
return base64.b64encode(stream)
# 获得tn的值,后续做DES加密用
# 通过测试
def get_tn(o: dict):
sorted_keys = sorted(o.keys())
result_list = []
for i in sorted_keys:
v = o[i]
if isinstance(v, (int, float)):
v = str(v * 10000)
elif isinstance(v, dict):
v = get_tn(v)
result_list.append(v)
return "".join(result_list)
def get_smid():
t = time.localtime()
_time = "{}{:0>2d}{:0>2d}{:0>2d}{:0>2d}{:0>2d}".format(
t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec
)
uid = str(uuid.uuid4())
v = _time + hashlib.md5(uid.encode("utf-8")).hexdigest() + "00"
smsk_web = hashlib.md5(("smsk_web_" + v).encode("utf-8")).hexdigest()[0:14]
return v + smsk_web + "0"
def get_d_id():
# storageName = '.thumbcache_' + md5(SM_CONFIG['organization']) // 用于从本地存储获得值
# uid = uuid()
# priId=md5(uid)[0:16]
# ep=rsa(uid,publicKey)
# SMID = localStorage.get(storageName);// 获得本地存储存的值
# _0x30b2eb为递归md5
uid = str(uuid.uuid4()).encode("utf-8")
priId = hashlib.md5(uid).hexdigest()[0:16]
# ep不一定对先走走看
ep = PK.encrypt(uid, padding.PKCS1v15())
ep = base64.b64encode(ep).decode("utf-8")
browser = BROWSER_ENV.copy()
current_time = int(time.time() * 1000)
browser.update(
{
"vpw": str(uuid.uuid4()),
"svm": current_time,
"trees": str(uuid.uuid4()),
"pmf": current_time,
}
)
des_target = {
**browser,
"protocol": 102,
"organization": SM_CONFIG["organization"],
"appId": SM_CONFIG["appId"],
"os": "web",
"version": "3.0.0",
"sdkver": "3.0.0",
"box": "", # 似乎是个SMID但是第一次的时候是空,不过不影响结果
"rtype": "all",
"smid": get_smid(),
"subVersion": "1.0.0",
"time": 0,
}
des_target["tn"] = hashlib.md5(get_tn(des_target).encode()).hexdigest()
des_result = _AES(GZIP(_DES(des_target)), priId.encode("utf-8"))
response = requests.post(
devices_info_url,
json={
"appId": "default",
"compress": 2,
"data": des_result,
"encode": 5,
"ep": ep,
"organization": SM_CONFIG["organization"],
"os": "web", # 固定值
},
)
resp = response.json()
if resp["code"] != 1100:
raise Exception("did计算失败请联系作者")
# 开头必须是B
return "B" + resp["detail"]["deviceId"]

View file

@ -8,7 +8,7 @@ from pydantic import BaseModel
class PlanConf(BaseModel):
ling_xi: int = 1
"令夕模式1感知 2烟火 3均衡"
max_resting_count: int = 4
max_resting_count: int = 0
"最大组人数"
exhaust_require: str = ""
"耗尽"

View file

@ -6,6 +6,7 @@ import pandas as pd
# from .log import logger
from mower.data import key_mapping
from mower.utils.log import logger
# from typing import Dict, List, Union
from mower.utils.path import get_path
@ -17,13 +18,10 @@ def 读取仓库():
创建json()
with open(path, "r", encoding="utf-8") as f:
depotinfo = json.load(f)
depotinfo = {
"code": 0,
"message": "OK",
"timestamp": "0",
"data": {"items": [{"id": "0", "count": "0"}]},
}
物品数量 = depotinfo["data"]["items"]
logger.info(depotinfo["timestamp"])
time = int(depotinfo["timestamp"])
新物品1 = {
key_mapping[item["id"]][2]: int(item["count"])
for item in 物品数量
@ -43,7 +41,7 @@ def 读取仓库():
新物品json = {}
for item in 新物品:
新物品json[key_mapping[item][0]] = 新物品[item]
time = depotinfo.iloc[-1, 0]
# time = depotinfo.iloc[-1, 0]
sort = {
"A常用": [

View file

@ -34,3 +34,13 @@ def network_check_cancel(solver: BaseSolver):
@edge(Scene.MOON_FESTIVAL, Scene.SIGN_IN_DAILY)
def moon_festival(solver: BaseSolver):
solver.back()
@edge(Scene.STORY, Scene.STORY_SKIP)
def skip_story(solver: BaseSolver):
solver.tap((1655, 781))
@edge(Scene.STORY_SKIP, Scene.OPERATOR_BEFORE)
def skip_story_confirm(solver: BaseSolver):
solver.tap_element("story_skip_confirm_dialog", x_rate=0.94)

View file

@ -16,7 +16,7 @@ from .utils import edge
@edge(Scene.ACTIVITY_CHOOSE_LEVEL, Scene.ACTIVITY_MAIN)
@edge(Scene.OPERATOR_SUPPORT, Scene.OPERATOR_SELECT)
@edge(Scene.OPERATOR_AGENT_SELECT, Scene.OPERATOR_SELECT)
@edge(Scene.OPERATOR_STRANGER_SUPPORT, Scene.OPERATOR_SUPPORT)
@edge(Scene.OPERATOR_SUPPORT_AGENT, Scene.OPERATOR_SUPPORT)
@edge(Scene.OPERATOR_ELIMINATE_AGENCY, Scene.OPERATOR_ELIMINATE)
def operation_back(solver: BaseSolver):
solver.back()

View file

@ -158,7 +158,7 @@ class Recognizer:
self.scene = Scene.OPERATOR_SUPPORT
elif self.find("fight/collection") or self.find("fight/collection_on"):
self.scene = Scene.OPERATOR_AGENT_SELECT
elif self.find("ope_select_start"):
elif self.find("choose_agent/fast_select"):
self.scene = Scene.OPERATOR_SELECT
elif self.find("ope_eliminate"):
self.scene = Scene.OPERATOR_ELIMINATE
@ -204,8 +204,6 @@ class Recognizer:
self.scene = Scene.LOGIN_MAIN
else:
self.scene = Scene.LOGIN_MAIN_NOENTRY
elif self.find("login_loading"):
self.scene = Scene.LOGIN_LOADING
elif self.find("12cadpa"):
self.scene = Scene.LOGIN_START
elif self.find("login_bilibili"):
@ -342,10 +340,12 @@ class Recognizer:
self.scene = Scene.OPERATOR_CHOOSE_LEVEL
elif self.find("ope_agency_going"):
self.scene = Scene.OPERATOR_ONGOING
elif self.find("fight/gear"):
self.scene = Scene.OPERATOR_FIGHT
elif self.find("ope_finish"):
self.scene = Scene.OPERATOR_FINISH
elif self.find("fight/use"):
self.scene = Scene.OPERATOR_STRANGER_SUPPORT
self.scene = Scene.OPERATOR_SUPPORT_AGENT
elif self.find("business_card"):
self.scene = Scene.BUSINESS_CARD
elif self.find("friend_list"):
@ -380,6 +380,10 @@ class Recognizer:
self.scene = Scene.CHOOSE_PRODUCT
elif self.find("order_switching_notice"):
self.scene = Scene.SWITCH_ORDER
elif self.find("story_skip_confirm_dialog"):
self.scene = Scene.STORY_SKIP
elif self.find("story_skip"):
self.scene = Scene.STORY
# 没弄完的
# elif self.find("ope_elimi_finished"):

View file

@ -1,10 +1,10 @@
color = {
"1800": (158, 958),
"12cadpa": (1810, 21),
"arrange_confirm": (755, 903),
"1800": (158, 958),
"arrange_order_options": (1652, 23),
"arrange_order_options_scene": (369, 199),
"choose_agent/clear": (685, 996),
"choose_agent/fast_select": ((1296, 25), (1592, 98)),
"clue": (1740, 855),
"clue/daily": (526, 623),
"clue/filter_all": (1297, 99),
@ -20,9 +20,9 @@ color = {
"double_confirm/infrastructure": (1077, 435),
"double_confirm/main": (835, 683),
"double_confirm/network": (708, 435),
"double_confirm/product_plan": (921, 461),
"double_confirm/recruit": (981, 464),
"double_confirm/voice": (745, 435),
"double_confirm/product_plan": (921, 461),
"drone": (274, 437),
"factory_collect": (1542, 886),
"fight/collection": (1088, 25),
@ -46,17 +46,15 @@ color = {
"mission_trainee_on": (690, 17),
"nav_bar": (655, 0),
"nav_button": (26, 20),
"navigation/activity/banner": (1285, 946),
"navigation/activity/entry": (1460, 640),
"navigation/collection/AP-1": (203, 821),
"navigation/collection/CA-1": (203, 821),
"navigation/collection/CE-1": (243, 822),
"navigation/collection/LS-1": (240, 822),
"navigation/collection/SK-1": (204, 821),
"navigation/collection/PR-A-1": (550, 629),
"navigation/collection/PR-B-1": (496, 629),
"navigation/collection/PR-C-1": (487, 586),
"navigation/collection/PR-D-1": (516, 619),
"navigation/collection/SK-1": (204, 821),
"navigation/ope_hard_small": (819, 937),
"navigation/ope_normal_small": (494, 930),
"navigation/record_restoration": (274, 970),
@ -68,7 +66,6 @@ color = {
"ope_eliminate": (1332, 938),
"ope_recover_originite_on": (1514, 124),
"ope_recover_potion_on": (1046, 127),
"ope_select_start": (1579, 701),
"open_recruitment": (192, 143),
"order_label": (404, 137),
"pull_once": (1260, 950),
@ -98,8 +95,8 @@ color = {
"sss/loading": (1642, 517),
"sss/main": (1224, 60),
"sss/redeploy": (1644, 970),
"sss/start": (1547, 968),
"sss/squad": (1645, 970),
"sss/start": (1547, 968),
"sss/terminated": (29, 241),
"terminal_main": (1658, 734),
}
@ -107,11 +104,13 @@ color = {
template_matching = {
"arrange_check_in": ((30, 300), (175, 700)),
"arrange_check_in_on": ((30, 300), (175, 700)),
"arrange_confirm": (755, 903),
"biography": (768, 934),
"business_card": (55, 165),
"collection": (1005, 943),
"collection_small": (1053, 982),
"connecting": (1087, 978),
"credit_visiting": (78, 220),
"choose_agent/profession/ALL": (1828, 46),
"choose_agent/profession/choose_arrow": ((1850, 125), (1920, 1080)),
"choose_agent/profession/CASTER": (1825, 630),
@ -125,11 +124,25 @@ template_matching = {
"choose_product_options": (1174, 23),
"episode": (535, 937),
"factory_accelerate": (1800, 775),
"fight/use": (858, 864),
"fight/gear": (82, 45),
"fight/use": (1037, 845),
"friend_list": (61, 306),
"credit_visiting": (78, 220),
"infra_no_operator": None,
"icon_notification_black": ((1436, 129), (1920, 221)),
"infra_complete/信用": None,
"infra_complete/先锋双芯片": None,
"infra_complete/医疗双芯片": None,
"infra_complete/合成玉": None,
"infra_complete/术师双芯片": None,
"infra_complete/源石碎片": None,
"infra_complete/特种双芯片": None,
"infra_complete/狙击双芯片": None,
"infra_complete/经验": None,
"infra_complete/赤金": None,
"infra_complete/辅助双芯片": None,
"infra_complete/近卫双芯片": None,
"infra_complete/重装双芯片": None,
"infra_complete/龙门币": None,
"infra_no_operator": None,
"loading": (736, 333),
"loading2": (620, 247),
"loading3": (1681, 1000),
@ -139,52 +152,66 @@ template_matching = {
"materiel_ico": (892, 61),
"mission_daily_on": ((685, 15), (1910, 100)),
"mission_weekly_on": ((685, 15), (1910, 100)),
"navigation/activity/banner": (1468, 855),
"navigation/activity/entry": (1256, 829),
"navigation/collection/AP_entry": ((0, 170), (1920, 870)),
"navigation/collection/CA_entry": ((0, 170), (1920, 870)),
"navigation/collection/CE_entry": ((0, 170), (1920, 870)),
"navigation/collection/LS_entry": ((0, 170), (1920, 870)),
"navigation/collection/SK_entry": ((0, 170), (1920, 870)),
"navigation/collection/PR-A_entry": ((0, 170), (1920, 870)),
"navigation/collection/PR-B_entry": ((0, 170), (1920, 870)),
"navigation/collection/PR-C_entry": ((0, 170), (1920, 870)),
"navigation/collection/PR-D_entry": ((0, 170), (1920, 870)),
"navigation/collection/SK_entry": ((0, 170), (1920, 870)),
"navigation/episode": (1567, 949),
"navigation/ope_difficulty": [(0, 920), (120, 1080)],
"navigation/ope_normal": (172, 950),
"navigation/ope_normal_small": (494, 930),
"navigation/ope_hard": (172, 950),
"navigation/ope_hard_small": (819, 937),
"ope_agency_going": ((508, 941), (715, 1021)),
"navigation/ope_normal": (172, 950),
"navigation/ope_normal_small": (494, 930),
"ope_agency_fail": (809, 959),
"ope_agency_going": ((508, 941), (715, 1021)),
"ope_failed": (183, 465),
"ope_finish": (87, 265),
"ope_plan": (1278, 24),
"ope_select_start": ((1579, 701), (1731, 921)),
"ope_select_start_empty": ((0, 0), (400, 400)),
"order_ready": (500, 664),
"order_switching_notice": (604, 900),
"ope_select_start_empty": ((0, 0), (400, 400)),
"product/先锋双芯片": ((1635, 445), (1730, 520)),
"product/医疗双芯片": ((1635, 445), (1730, 520)),
"product/术师双芯片": ((1635, 445), (1730, 520)),
"product/源石碎片": ((1635, 445), (1730, 520)),
"product/特种双芯片": ((1635, 445), (1730, 520)),
"product/狙击双芯片": ((1635, 445), (1730, 520)),
"product/经验": ((1635, 445), (1730, 520)),
"product/赤金": ((1635, 445), (1730, 520)),
"product/辅助双芯片": ((1635, 445), (1730, 520)),
"product/近卫双芯片": ((1635, 445), (1730, 520)),
"product/重装双芯片": ((1635, 445), (1730, 520)),
"recruit/agent_token": ((1740, 765), (1920, 805)),
"recruit/agent_token_first": ((1700, 760), (1920, 810)),
"recruit/available_level": (1294, 234),
"recruit/begin_recruit": None,
"recruit/career_needs": (350, 593),
"recruit/job_requirements": None,
"recruit/lmb": (945, 27),
"recruit/recruit_done": None,
"recruit/recruit_lock": None,
"recruit/job_requirements": None,
"recruit/ticket": ((900, 0), (1920, 120)),
"recruit/time": (1304, 112),
"recruit/refresh": (1366, 560),
"recruit/refresh_comfirm": (1237, 714),
"recruit/riic_res/CASTER": ((750, 730), (1920, 860)),
"recruit/riic_res/MEDIC": ((750, 730), (1920, 860)),
"recruit/riic_res/PIONEER": ((750, 730), (1920, 860)),
"recruit/riic_res/SPECIAL": ((750, 730), (1920, 860)),
"recruit/riic_res/SNIPER": ((750, 730), (1920, 860)),
"recruit/riic_res/SPECIAL": ((750, 730), (1920, 860)),
"recruit/riic_res/SUPPORT": ((750, 730), (1920, 860)),
"recruit/riic_res/TANK": ((750, 730), (1920, 860)),
"recruit/riic_res/WARRIOR": ((750, 730), (1920, 860)),
"recruit/start_recruit": (1438, 849),
"recruit/stone": ((900, 0), (1920, 120)),
"recruit/ticket": ((900, 0), (1920, 120)),
"recruit/time": (1304, 112),
"reload_check": (1252, 772),
"riic/assistants": ((1320, 400), (1600, 650)),
"riic/iron": ((1570, 230), (1630, 340)),
@ -192,36 +219,13 @@ template_matching = {
"riic/trade": ((1320, 250), (1600, 500)),
"sign_in/moon_festival/banner": (704, 92),
"stone_fragment": None,
"story_skip": (1718, 58),
"story_skip_confirm_dialog": (685, 655),
"switch_order/check": None,
"switch_order/lmb": (1442, 891),
"switch_order/oru": (1442, 891),
"switch_order/check": None,
"terminal_regular": (1247, 980),
"upgrade": (997, 501),
"product/经验": ((1635, 445), (1730, 520)),
"product/赤金": ((1635, 445), (1730, 520)),
"product/源石碎片": ((1635, 445), (1730, 520)),
"product/先锋双芯片": ((1635, 445), (1730, 520)),
"product/近卫双芯片": ((1635, 445), (1730, 520)),
"product/重装双芯片": ((1635, 445), (1730, 520)),
"product/术师双芯片": ((1635, 445), (1730, 520)),
"product/特种双芯片": ((1635, 445), (1730, 520)),
"product/医疗双芯片": ((1635, 445), (1730, 520)),
"product/辅助双芯片": ((1635, 445), (1730, 520)),
"product/狙击双芯片": ((1635, 445), (1730, 520)),
"infra_complete/赤金": None,
"infra_complete/经验": None,
"infra_complete/合成玉": None,
"infra_complete/源石碎片": None,
"infra_complete/龙门币": None,
"infra_complete/信用": None,
"infra_complete/特种双芯片": None,
"infra_complete/先锋双芯片": None,
"infra_complete/近卫双芯片": None,
"infra_complete/辅助双芯片": None,
"infra_complete/医疗双芯片": None,
"infra_complete/重装双芯片": None,
"infra_complete/术师双芯片": None,
"infra_complete/狙击双芯片": None,
}
template_matching_score = {
@ -240,18 +244,19 @@ template_matching_score = {
"navigation/ope_hard_small": 0.7,
"navigation/ope_normal": 0.7,
"navigation/ope_normal_small": 0.7,
"ope_select_start": 0.7,
"recruit/agent_token": 0.8,
"recruit/agent_token_first": 0.8,
"recruit/lmb": 0.7,
"recruit/riic_res/CASTER": 0.7,
"recruit/riic_res/MEDIC": 0.7,
"recruit/riic_res/PIONEER": 0.7,
"recruit/riic_res/SPECIAL": 0.7,
"recruit/riic_res/SNIPER": 0.7,
"recruit/riic_res/SPECIAL": 0.7,
"recruit/riic_res/SUPPORT": 0.7,
"recruit/riic_res/TANK": 0.7,
"recruit/riic_res/WARRIOR": 0.7,
"recruit/time": 0.8,
"recruit/stone": 0.7,
"recruit/time": 0.8,
"sign_in/moon_festival/banner": 0.5,
}

View file

@ -18,7 +18,7 @@ class Scene:
UPGRADE = 6
"升级"
SKIP = 7
"跳过"
"开包动画"
DOUBLE_CONFIRM = 8
"二次确认(未知)"
CONNECTING = 9
@ -37,6 +37,10 @@ class Scene:
"首页源石换玉"
INDEX_SANITY = 16
"首页源石换理智"
STORY = 17
"作战剧情"
STORY_SKIP = 18
"作战剧情"
LOGIN_MAIN = 101
"登录页面"
LOGIN_INPUT = 102
@ -183,10 +187,12 @@ class Scene:
"剿灭代理卡使用确认"
OPERATOR_SUPPORT = 615
"借助战"
OPERATOR_STRANGER_SUPPORT = 616
"使用非好友助战"
OPERATOR_SUPPORT_AGENT = 616
"使用助战干员界面"
OPERATOR_AGENT_SELECT = 617
"作战干员选择界面"
OPERATOR_FIGHT = 618
"作战中"
SHOP_OTHERS = 701
"商店其它界面"
SHOP_CREDIT = 702
@ -321,7 +327,7 @@ SceneComment = {
4: "邮件信箱",
5: "导航栏返回",
6: "升级",
7: "跳过",
7: "开包动画",
8: "二次确认(未知)",
9: "正在提交反馈至神经",
10: "网络拨测",
@ -331,6 +337,8 @@ SceneComment = {
14: "说明",
15: "首页源石换玉",
16: "首页源石换理智",
17: "作战剧情",
18: "作战剧情",
101: "登录页面",
102: "登录页面(输入)",
103: "登录页面(快速)",
@ -404,8 +412,9 @@ SceneComment = {
613: "代理作战失败",
614: "剿灭代理卡使用确认",
615: "借助战",
616: "使用非好友助战",
616: "使用助战干员界面",
617: "作战干员选择界面",
618: "作战中",
701: "商店其它界面",
702: "信用交易所",
703: "信用交易所兑换确认",

148
mower/utils/skland.py Normal file
View file

@ -0,0 +1,148 @@
import hashlib
import hmac
import json
import time
from urllib import parse
import requests
from mower.utils.log import logger
from mower.utils.SecuritySm import get_d_id
app_code = "4ca99fa6b56cc2ba"
# 签到url
sign_url = "https://zonai.skland.com/api/v1/game/attendance"
# 绑定的角色url
binding_url = "https://zonai.skland.com/api/v1/game/player/binding"
# 验证码url
login_code_url = "https://as.hypergryph.com/general/v1/send_phone_code"
# 验证码登录
token_phone_code_url = "https://as.hypergryph.com/user/auth/v2/token_by_phone_code"
# 密码登录
token_password_url = "https://as.hypergryph.com/user/auth/v1/token_by_phone_password"
# 使用token获得认证代码
grant_code_url = "https://as.hypergryph.com/user/oauth2/v2/grant"
# 使用认证代码获得cred
cred_code_url = "https://zonai.skland.com/web/v1/user/auth/generate_cred_by_code"
header = {
"cred": "",
"User-Agent": "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0",
"Accept-Encoding": "gzip",
"Connection": "close",
}
header_login = {
"User-Agent": "Skland/1.0.1 (com.hypergryph.skland; build:100001014; Android 31; ) Okhttp/4.11.0",
"Accept-Encoding": "gzip",
"Connection": "close",
"dId": get_d_id(),
}
header_for_sign = {"platform": "", "timestamp": "", "dId": "", "vName": ""}
def generate_signature(token: str, path, body_or_query):
"""
获得签名头
接口地址+方法为Get请求用query否则用body+时间戳+ 请求头的四个重要参数dIdplatformtimestampvName.toJSON()
将此字符串做HMAC加密算法为SHA-256密钥token为请求cred接口会返回的一个token值
再将加密后的字符串做MD5即得到sign
:param token: 拿cred时候的token
:param path: 请求路径不包括网址
:param body_or_query: 如果是GET则是它的queryPOST则为它的body
:return: 计算完毕的sign
"""
# 总是说请勿修改设备时间怕不是yj你的服务器有问题吧所以这里特地-2
t = str(int(time.time()) - 2)
token = token.encode("utf-8")
header_ca = json.loads(json.dumps(header_for_sign))
header_ca["timestamp"] = t
header_ca_str = json.dumps(header_ca, separators=(",", ":"))
s = path + body_or_query + t + header_ca_str
hex_s = hmac.new(token, s.encode("utf-8"), hashlib.sha256).hexdigest()
md5 = hashlib.md5(hex_s.encode("utf-8")).hexdigest().encode("utf-8").decode("utf-8")
return md5, header_ca
def get_sign_header(url: str, method, body, sign_token, old_header=header):
h = json.loads(json.dumps(old_header))
p = parse.urlparse(url)
if method.lower() == "get":
h["sign"], header_ca = generate_signature(sign_token, p.path, p.query)
else:
h["sign"], header_ca = generate_signature(sign_token, p.path, json.dumps(body))
for i in header_ca:
h[i] = header_ca[i]
return h
def get_grant_code(token):
response = requests.post(
grant_code_url,
json={"appCode": app_code, "token": token, "type": 0},
headers=header_login,
)
resp = response.json()
if response.status_code != 200:
raise Exception(f"获得认证代码失败:{resp}")
if resp.get("status") != 0:
raise Exception(f'获得认证代码失败:{resp["msg"]}')
return resp["data"]["code"]
def get_cred(grant):
"""
获取cred
:param cred_code_url: 获取cred的URL
:param grant: 授权代码
:param header_login: 登录请求头
:return: cred
"""
resp = requests.post(
cred_code_url, json={"code": grant, "kind": 1}, headers=header_login
).json()
if resp["code"] != 0:
raise Exception(f'获得cred失败{resp["message"]}')
return resp["data"]
def get_binding_list(sign_token):
v = []
resp = requests.get(
binding_url,
headers=get_sign_header(
binding_url,
"get",
None,
sign_token,
),
).json()
if resp["code"] != 0:
logger.info(f"请求角色列表出现问题:{resp['message']}")
if resp.get("message") == "用户未登录":
logger.warning("用户登录可能失效了,请重新运行此程序!")
return []
for i in resp["data"]["list"]:
if i.get("appCode") != "arknights":
continue
v.extend(i.get("bindingList"))
return v
def get_cred_by_token(token):
return get_cred(get_grant_code(token))
def log(account):
r = requests.post(
token_password_url,
json={"phone": account.account, "password": account.password},
headers=header_login,
).json()
if r.get("status") != 0:
raise Exception(f'获得token失败{r["msg"]}')
logger.info("森空岛登陆成功")
return r["data"]["token"]

View file

@ -18,7 +18,27 @@ Res = Literal[
"choose_agent/clear",
"choose_agent/clear_battle",
"choose_agent/confirm",
"choose_agent/empty_skill_slot",
"choose_agent/fast_select",
"choose_agent/foldup",
"choose_agent/open_profession",
"choose_agent/perfer",
"choose_agent/perfer_agent",
"choose_agent/perfer_choosed",
"choose_agent/profession/ALL",
"choose_agent/profession/CASTER",
"choose_agent/profession/choose_arrow",
"choose_agent/profession/MEDIC",
"choose_agent/profession/PIONEER",
"choose_agent/profession/skill",
"choose_agent/profession/SNIPER",
"choose_agent/profession/SPECIAL",
"choose_agent/profession/SUPPORT",
"choose_agent/profession/TANK",
"choose_agent/profession/WARRIOR",
"choose_agent/rect",
"choose_agent/riic_empty",
"choose_agent/trigger",
"choose_product_options",
"clue/1",
"clue/2",
@ -93,10 +113,14 @@ Res = Literal[
"fight/complete",
"fight/enemy",
"fight/failed_text",
"fight/gear",
"fight/kills_separator",
"fight/light",
"fight/pause",
"fight/refresh",
"fight/skill_be_choosen",
"fight/skill_ready",
"fight/skill_stop",
"fight/use",
"friend_list",
"friend_visit",
@ -143,7 +167,6 @@ Res = Literal[
"login_bilibili_privacy",
"login_captcha",
"login_connecting",
"login_loading",
"login_logo",
"mail",
"main_theme",
@ -431,6 +454,8 @@ Res = Literal[
"sss/start",
"sss/terminated",
"start",
"story_skip",
"story_skip_confirm_dialog",
"switch_order/check",
"switch_order/lmb",
"switch_order/oru",

View file

@ -18,4 +18,4 @@ def sa(scope: tp.Scope, vector: tp.Coordinate) -> tp.Scope:
def sm(a: float, v: tp.Coordinate) -> tp.Coordinate:
"""数乘向量scalar multiply"""
return a * v[0], a * v[1]
return round(a * v[0]), round(a * v[1])

View file

@ -55,3 +55,9 @@ Jinja2==3.1.4
# 启动模拟器后按快捷键
PyAutoGUI==0.9.54
# 森空岛检测
cryptography==43.0.1
# 数据库ORM
SQLAlchemy==2.0.35

View file

@ -10,18 +10,31 @@ base45==0.4.4
# via -r requirements.in
blinker==1.8.2
# via flask
bottle==0.12.25
bottle==0.13.1
# via pywebview
certifi==2024.7.4
certifi==2024.8.30
# via requests
cffi==1.17.1
# via
# clr-loader
# cryptography
charset-normalizer==3.3.2
# via requests
click==8.1.7
# via flask
clr-loader==0.2.6
# via pythonnet
colorama==0.4.6
# via
# click
# colorlog
# qrcode
coloredlogs==15.0.1
# via onnxruntime
colorlog==6.8.2
# via -r requirements.in
cryptography==43.0.1
# via -r requirements.in
evalidate==2.0.2
# via -r requirements.in
flask==3.0.3
@ -35,13 +48,15 @@ flask-sock==0.7.0
# via -r requirements.in
flatbuffers==24.3.25
# via onnxruntime
greenlet==3.1.1
# via sqlalchemy
h11==0.14.0
# via wsproto
humanfriendly==10.0
# via coloredlogs
idna==3.7
idna==3.10
# via requests
imageio==2.34.2
imageio==2.35.1
# via scikit-image
itsdangerous==2.2.0
# via flask
@ -55,7 +70,7 @@ jsonpickle==3.0.4
# via -r requirements.in
lazy-loader==0.4
# via scikit-image
markupsafe==2.1.5
markupsafe==3.0.0
# via
# jinja2
# werkzeug
@ -80,7 +95,7 @@ numpy==1.26.4
# scipy
# shapely
# tifffile
onnxruntime==1.18.1
onnxruntime==1.19.2
# via rapidocr-onnxruntime
opencv-python==4.9.0.80
# via
@ -100,7 +115,7 @@ pillow==10.3.0
# pystray
# rapidocr-onnxruntime
# scikit-image
protobuf==5.27.2
protobuf==5.28.2
# via onnxruntime
proxy-tools==0.1.0
# via pywebview
@ -108,6 +123,8 @@ pyautogui==0.9.54
# via -r requirements.in
pyclipper==1.3.0.post5
# via rapidocr-onnxruntime
pycparser==2.22
# via cffi
pydantic==2.8.2
# via -r requirements.in
pydantic-core==2.20.1
@ -120,20 +137,18 @@ pyperclip==1.9.0
# via mouseinfo
pypng==0.20220715.0
# via qrcode
pyreadline3==3.5.4
# via humanfriendly
pyrect==0.2.0
# via pygetwindow
pyscreeze==0.1.30
pyscreeze==1.0.1
# via pyautogui
pystray==0.19.5
# via -r requirements.in
python-dateutil==2.9.0.post0
# via pandas
python-xlib==0.33
# via pystray
python3-xlib==0.15
# via
# mouseinfo
# pyautogui
pythonnet==3.0.4
# via pywebview
pytweening==1.2.0
# via pyautogui
pytz==2024.1
@ -163,7 +178,7 @@ scipy==1.13.0
# -r requirements.in
# scikit-image
# scikit-learn
shapely==2.0.5
shapely==2.0.6
# via rapidocr-onnxruntime
simple-websocket==1.0.0
# via flask-sock
@ -171,13 +186,14 @@ six==1.16.0
# via
# pystray
# python-dateutil
# python-xlib
# rapidocr-onnxruntime
sympy==1.13.0
sqlalchemy==2.0.35
# via -r requirements.in
sympy==1.13.3
# via onnxruntime
threadpoolctl==3.5.0
# via scikit-learn
tifffile==2024.7.2
tifffile==2024.9.20
# via scikit-image
typing-extensions==4.12.2
# via
@ -185,13 +201,16 @@ typing-extensions==4.12.2
# pydantic-core
# pywebview
# qrcode
tzdata==2024.1
# via pandas
# sqlalchemy
tzdata==2024.2
# via
# pandas
# tzlocal
tzlocal==5.2
# via -r requirements.in
urllib3==2.2.1
urllib3==2.2.3
# via requests
werkzeug==3.0.3
werkzeug==3.0.4
# via flask
wsproto==1.2.0
# via simple-websocket

119
server.py
View file

@ -18,6 +18,7 @@ from tzlocal import get_localzone
from werkzeug.exceptions import NotFound
from mower import __system__
from mower.solvers.infra.report import ReportSolver
from mower.utils import config
from mower.utils.log import logger
from mower.utils.path import get_path
@ -145,9 +146,10 @@ def activity():
@app.route("/depot/readdepot")
def read_depot():
from mower.utils import depot
from mower.solvers.depot_reader import DepotManager
return depot.读取仓库()
a = DepotManager()
return a.读取仓库()
@app.route("/running")
@ -401,119 +403,14 @@ def date2str(target: datetime.date):
@app.route("/report/getReportData")
def get_report_data():
import pandas as pd
record_path = get_path("@app/tmp/report.csv")
try:
format_data = []
if os.path.exists(record_path) is False:
logger.debug("基报不存在")
return False
df = pd.read_csv(record_path, encoding="gbk")
data = df.to_dict("records")
earliest_date = str2date(data[0]["Unnamed: 0"])
for item in data:
format_data.append(
{
"日期": date2str(
str2date(item["Unnamed: 0"]) - datetime.timedelta(days=1)
),
"作战录像": item["作战录像"],
"赤金": item["赤金"],
"制造总数": int(item["赤金"] + item["作战录像"]),
"龙门币订单": item["龙门币订单"],
"反向作战录像": -item["作战录像"],
"龙门币订单数": item["龙门币订单数"],
"每单获取龙门币": int(item["龙门币订单"] / item["龙门币订单数"]),
}
)
if len(format_data) < 15:
for i in range(1, 16 - len(format_data)):
format_data.insert(
0,
{
"日期": date2str(
earliest_date - datetime.timedelta(days=i + 1)
),
"作战录像": "-",
"赤金": "-",
"龙门币订单": "-",
"龙门币订单数": "-",
"每单获取龙门币": "-",
},
)
logger.debug(format_data)
return format_data
except PermissionError:
logger.info("report.csv正在被占用")
a = ReportSolver()
return a.get_report_data()
@app.route("/report/getOrundumData")
def get_orundum_data():
import pandas as pd
record_path = get_path("@app/tmp/report.csv")
try:
format_data = []
if os.path.exists(record_path) is False:
logger.debug("基报不存在")
return False
df = pd.read_csv(record_path, encoding="gbk")
data = df.to_dict("records")
earliest_date = datetime.datetime.now()
begin_make_orundum = (earliest_date + datetime.timedelta(days=1)).date()
print(begin_make_orundum)
if len(data) >= 15:
for i in range(len(data) - 1, -1, -1):
if 0 < i < len(data) - 15:
data.pop(i)
else:
logger.debug("合成玉{}".format(data[i]["合成玉"]))
if data[i]["合成玉"] > 0:
begin_make_orundum = str2date(data[i]["Unnamed: 0"])
else:
for item in data:
if item["合成玉"] > 0:
begin_make_orundum = str2date(item["Unnamed: 0"])
if begin_make_orundum > earliest_date.date():
return format_data
total_orundum = 0
for item in data:
total_orundum = total_orundum + item["合成玉"]
format_data.append(
{
"日期": date2str(
str2date(item["Unnamed: 0"]) - datetime.timedelta(days=1)
),
"合成玉": item["合成玉"],
"合成玉订单数量": item["合成玉订单数量"],
"抽数": round((item["合成玉"] / 600), 1),
"累计制造合成玉": total_orundum,
}
)
if len(format_data) < 15:
earliest_date = str2date(data[0]["Unnamed: 0"])
for i in range(1, 16 - len(format_data)):
format_data.insert(
0,
{
"日期": date2str(
earliest_date - datetime.timedelta(days=i + 1)
),
"合成玉": "-",
"合成玉订单数量": "-",
"抽数": "-",
"累计制造合成玉": 0,
},
)
logger.debug(format_data)
return format_data
except PermissionError:
logger.info("report.csv正在被占用")
a = ReportSolver()
return a.get_orundum_data()
@app.route("/test-email")

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.link-container[data-v-434bc35b]{width:100%;padding:6px 12px 0;box-sizing:border-box}
.link-container[data-v-4abe2846]{width:100%;padding:6px 12px 0;box-sizing:border-box}

View file

@ -1 +1 @@
import{br as r,bC as n,by as o,k as e,bw as a,bv as i,F as l,bt as m}from"./_plugin-vue_export-helper.js";import{_ as d}from"./a.js";import"./main.js";const p={},_={class:"link-container"};function c(b,t){const s=d;return m(),n(l,null,[o("div",_,[t[1]||(t[1]=e(" 在线文档地址: ")),a(s,{href:"https://arkmowers.github.io/arknights-mower/",target:"_blank"},{default:i(()=>t[0]||(t[0]=[e(" https://arkmowers.github.io/arknights-mower/ ")])),_:1})]),t[2]||(t[2]=o("iframe",{src:"/docs/index.html",sandbox:"allow-popups allow-scripts allow-same-origin allow-forms",style:{width:"100%",height:"100vh",border:"none"}},null,-1))],64)}const g=r(p,[["render",c],["__scopeId","data-v-434bc35b"]]);export{g as default};
import{br as r,bC as a,by as o,k as e,bw as n,bv as i,F as l,bt as m}from"./_plugin-vue_export-helper.js";import{_ as d}from"./a.js";import"./main.js";const p={},_={class:"link-container"};function c(b,t){const s=d;return m(),a(l,null,[o("div",_,[t[1]||(t[1]=e(" 在线文档地址: ")),n(s,{href:"https://arkmowers.github.io/arknights-mower/",target:"_blank"},{default:i(()=>t[0]||(t[0]=[e(" https://arkmowers.github.io/arknights-mower/ ")])),_:1})]),t[2]||(t[2]=o("iframe",{src:"/docs/index.html",sandbox:"allow-popups allow-scripts allow-same-origin allow-forms",style:{width:"100%",height:"100vh",border:"none"}},null,-1))],64)}const g=r(p,[["render",c],["__scopeId","data-v-4abe2846"]]);export{g as default};

View file

@ -1 +1 @@
.button_row[data-v-fa1cd4c9]{margin-top:8px}.task_row[data-v-fa1cd4c9]{display:flex;align-items:center;gap:8px;width:100%}.task_row .n-input[data-v-fa1cd4c9]{width:140px}.outer[data-v-fa1cd4c9]{display:flex;flex-direction:row;align-items:center;gap:18px}.inner[data-v-fa1cd4c9]{display:flex;flex-direction:column;gap:8px}.task-col[data-v-fa1cd4c9]{display:flex;flex-direction:row;gap:8px;align-items:center}.n-dynamic-tags[data-v-fa1cd4c9]{align-items:center}.ml[data-v-fa1cd4c9]{margin-left:16px}.dropdown[data-v-3256832f]{padding-left:var(--5fec12ab);padding-right:var(--5fec12ab)}
.button_row[data-v-0b959ed7]{margin-top:8px}.task_row[data-v-0b959ed7]{display:flex;align-items:center;gap:8px;width:100%}.task_row .n-input[data-v-0b959ed7]{width:140px}.outer[data-v-0b959ed7]{display:flex;flex-direction:row;align-items:center;gap:18px}.inner[data-v-0b959ed7]{display:flex;flex-direction:column;gap:8px}.task-col[data-v-0b959ed7]{display:flex;flex-direction:row;gap:8px;align-items:center}.n-dynamic-tags[data-v-0b959ed7]{align-items:center}.ml[data-v-0b959ed7]{margin-left:16px}.dropdown[data-v-751873a1]{padding-left:var(--3750a4ee);padding-right:var(--3750a4ee)}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.help[data-v-5868d4d1]{z-index:100}
.help[data-v-a623cdce]{z-index:100}

View file

@ -1 +1 @@
import{br as l,bt as _,bu as a,bv as t,bw as e,by as o,K as p,aX as u,b3 as d}from"./_plugin-vue_export-helper.js";import{N as m}from"./main.js";const f={};function w(r,n){const s=u,c=d,i=m;return _(),a(i,{trigger:"hover"},{trigger:t(()=>[e(c,{tertiary:"",circle:"",class:"help",size:"tiny"},{icon:t(()=>[e(s,null,{default:t(()=>n[0]||(n[0]=[o("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},[o("path",{d:"M160 164s1.44-33 33.54-59.46C212.6 88.83 235.49 84.28 256 84c18.73-.23 35.47 2.94 45.48 7.82C318.59 100.2 352 120.6 352 164c0 45.67-29.18 66.37-62.35 89.18S248 298.36 248 324",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-miterlimit":"10","stroke-width":"40"}),o("circle",{cx:"248",cy:"399.99",r:"32",fill:"currentColor"})],-1)])),_:1})]),_:1})]),default:t(()=>[p(r.$slots,"default",{},void 0,!0)]),_:3})}const b=l(f,[["render",w],["__scopeId","data-v-5868d4d1"]]);export{b as _};
import{br as l,bt as _,bu as a,bv as t,bw as n,by as o,K as p,aX as u,b3 as d}from"./_plugin-vue_export-helper.js";import{N as m}from"./main.js";const f={};function w(r,e){const s=u,c=d,i=m;return _(),a(i,{trigger:"hover"},{trigger:t(()=>[n(c,{tertiary:"",circle:"",class:"help",size:"tiny"},{icon:t(()=>[n(s,null,{default:t(()=>e[0]||(e[0]=[o("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 512 512"},[o("path",{d:"M160 164s1.44-33 33.54-59.46C212.6 88.83 235.49 84.28 256 84c18.73-.23 35.47 2.94 45.48 7.82C318.59 100.2 352 120.6 352 164c0 45.67-29.18 66.37-62.35 89.18S248 298.36 248 324",fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-miterlimit":"10","stroke-width":"40"}),o("circle",{cx:"248",cy:"399.99",r:"32",fill:"currentColor"})],-1)])),_:1})]),_:1})]),default:t(()=>[p(r.$slots,"default",{},void 0,!0)]),_:3})}const b=l(f,[["render",w],["__scopeId","data-v-a623cdce"]]);export{b as _};

View file

@ -1 +1 @@
.log[data-v-97f6834c]{overflow:hidden;flex:1}.task-table[data-v-97f6834c]{max-width:600px}.task-table th[data-v-97f6834c]{padding:2px 16px}.task-table td[data-v-97f6834c]{height:24px;padding:2px 8px}.task-table td[data-v-97f6834c]:last-child{width:100%}.action-container[data-v-97f6834c]{display:flex;align-items:center;gap:12px}.scroll-container[data-v-97f6834c]{display:flex;align-items:center;gap:4px}.expand[data-v-97f6834c]{flex-grow:1}.toggle-table-collapse-btn[data-v-97f6834c]{position:absolute;top:12px;right:12px}.log-bg[data-v-97f6834c]{content:"";width:100%;height:100%;position:absolute;top:0;left:0;opacity:var(--23b16ac2);background-image:url(/bg.webp);background-repeat:no-repeat;background-size:cover;background-position:65% 50%;pointer-events:none}.hljs-date{color:#f0a020!important;font-weight:700}.hljs-time{color:#2080f0!important;font-weight:700}.hljs-room{color:#18a058!important;font-weight:700}.hljs-operator{color:#d03050!important}.hljs-info{font-weight:700}.hljs-warning{color:#f0a020!important;font-weight:700}.hljs-error{color:#d03050!important;font-weight:700}.hljs-scene{font-style:italic}
.log[data-v-9d004220]{overflow:hidden;flex:1}.task-table[data-v-9d004220]{max-width:600px}.task-table th[data-v-9d004220]{padding:2px 16px}.task-table td[data-v-9d004220]{height:24px;padding:2px 8px}.task-table td[data-v-9d004220]:last-child{width:100%}.action-container[data-v-9d004220]{display:flex;align-items:center;gap:12px}.scroll-container[data-v-9d004220]{display:flex;align-items:center;gap:4px}.expand[data-v-9d004220]{flex-grow:1}.toggle-table-collapse-btn[data-v-9d004220]{position:absolute;top:12px;right:12px}.log-bg[data-v-9d004220]{content:"";width:100%;height:100%;position:absolute;top:0;left:0;opacity:var(--3d2cf20e);background-image:url(/bg.webp);background-repeat:no-repeat;background-size:cover;background-position:65% 50%;pointer-events:none}.hljs-date{color:#f0a020!important;font-weight:700}.hljs-time{color:#2080f0!important;font-weight:700}.hljs-room{color:#18a058!important;font-weight:700}.hljs-operator{color:#d03050!important}.hljs-info{font-weight:700}.hljs-warning{color:#f0a020!important;font-weight:700}.hljs-error{color:#d03050!important;font-weight:700}.hljs-scene{font-style:italic}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.select-label[data-v-61f3d7ff]{width:44px}.type-select[data-v-61f3d7ff]{width:100px;margin-right:8px}.product-select[data-v-61f3d7ff]{width:180px;margin-right:8px}.operator-select[data-v-61f3d7ff]{width:220px}.replacement-select[data-v-61f3d7ff]{min-width:400px}.plan-container[data-v-61f3d7ff]{width:980px;min-width:980px;display:flex;flex-direction:column;gap:12px}.group[data-v-61f3d7ff]{width:160px}.facility-2[data-v-61f3d7ff]{width:124px;height:76px;margin:2px 3px}.facility-3[data-v-61f3d7ff]{width:175px;height:76px;margin:2px 3px}.facility-5[data-v-61f3d7ff]{width:277px;height:76px;margin:2px 3px}.avatars[data-v-61f3d7ff]{display:flex;gap:6px;z-index:5}.avatars img[data-v-61f3d7ff]{box-sizing:content-box;border-radius:2px;background:var(--84ca658c)}.facility-name[data-v-61f3d7ff]{margin-bottom:4px;text-align:center;line-height:1;display:flex;justify-content:space-around;z-index:5}.outer[data-v-61f3d7ff]{display:flex;margin:0 auto}.left_box[data-v-61f3d7ff]{display:flex;flex-direction:column;gap:4px;padding-top:82px;padding-right:2px}.left_box .left_contain[data-v-61f3d7ff]{display:grid;grid-template-columns:1fr 1fr 1fr;gap:4px}.left_box .left_contain>div[data-v-61f3d7ff]{box-sizing:border-box;width:175px;height:76px;cursor:pointer}.left_box .left_contain .info[data-v-61f3d7ff]{background-color:#2080f029;border-radius:3px;border:1px solid transparent;transition:all .3s;position:relative}.left_box .left_contain .info[data-v-61f3d7ff]:hover{background-color:#2080f038}.left_box .left_contain .info.true[data-v-61f3d7ff]{background-color:var(--n-color);border:1px solid rgb(32,128,240)}.left_box .left_contain .info .facility-name[data-v-61f3d7ff]{color:#2080f0}.left_box .left_contain .warning[data-v-61f3d7ff]{background-color:#f0a02029;border-radius:3px;border:1px solid transparent;transition:all .3s;position:relative}.left_box .left_contain .warning[data-v-61f3d7ff]:hover{background-color:#f0a02038}.left_box .left_contain .warning.true[data-v-61f3d7ff]{background-color:var(--n-color);border:1px solid rgb(240,160,32)}.left_box .left_contain .warning .facility-name[data-v-61f3d7ff]{color:#f0a020}.left_box .left_contain .primary[data-v-61f3d7ff]{background-color:#18a05829;border-radius:3px;border:1px solid transparent;transition:all .3s}.left_box .left_contain .primary[data-v-61f3d7ff]:hover{background-color:#18a05838}.left_box .left_contain .primary.true[data-v-61f3d7ff]{background-color:var(--n-color);border:1px solid rgb(24,160,88)}.left_box .left_contain .primary .facility-name[data-v-61f3d7ff]{color:#18a058}.mid_box[data-v-61f3d7ff]{display:flex;flex-direction:column}.waiting[data-v-61f3d7ff]{width:100%;height:100%;display:flex;align-items:center;justify-content:center;border:1px dashed rgb(51,54,57);opacity:.6;transition:all .3s;cursor:pointer;border-radius:3px}.waiting[data-v-61f3d7ff]:hover{opacity:1;border:1px dashed rgb(54,173,106);color:#36ad6a}.waiting div[data-v-61f3d7ff]{text-align:center}.draggable[data-v-61f3d7ff]{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center}.product-bg[data-v-61f3d7ff]{content:"";position:absolute;top:0;left:0;width:173px;height:74px;opacity:var(--7898b81c);background-repeat:no-repeat;background-size:100%;background-position:110px -20px;z-index:3;pointer-events:none}.avatar-wrapper[data-v-61f3d7ff]{position:relative}.workaholic[data-v-61f3d7ff]{position:absolute;content:"";top:0;left:0;width:45px;height:45px;opacity:.35;background-color:red;pointer-events:none}.n-base-selection-placeholder .n-avatar{display:none}.n-table[data-v-37669413]{min-width:100%}.n-table th[data-v-37669413]{width:124px;box-sizing:border-box}.label[data-v-37669413]{display:flex;flex-direction:row;align-items:center;gap:6px}.dropdown-container{display:flex;align-items:center;margin-top:5px}.dropdown-label{flex:0 0 40%;max-width:125px}.dropdown-select{flex:1}.w-980[data-v-d6372713]{width:100%;max-width:980px}.mx-auto[data-v-d6372713]{margin:0 auto}.mt-12[data-v-d6372713]{margin-top:12px}.mb-12[data-v-d6372713]{margin-bottom:12px}.px-12[data-v-d6372713]{padding:0 12px}.mw-980[data-v-d6372713]{min-width:980px}.plan-bar[data-v-d6372713]{display:flex;flex-direction:row;flex-grow:0;gap:6px;padding:0 12px}
.select-label[data-v-78258008]{width:44px}.type-select[data-v-78258008]{width:100px;margin-right:8px}.product-select[data-v-78258008]{width:180px;margin-right:8px}.operator-select[data-v-78258008]{width:220px}.replacement-select[data-v-78258008]{min-width:400px}.plan-container[data-v-78258008]{width:980px;min-width:980px;display:flex;flex-direction:column;gap:12px}.group[data-v-78258008]{width:160px}.facility-2[data-v-78258008]{width:124px;height:76px;margin:2px 3px}.facility-3[data-v-78258008]{width:175px;height:76px;margin:2px 3px}.facility-5[data-v-78258008]{width:277px;height:76px;margin:2px 3px}.avatars[data-v-78258008]{display:flex;gap:6px;z-index:5}.avatars img[data-v-78258008]{box-sizing:content-box;border-radius:2px;background:var(--3a9b0e51)}.facility-name[data-v-78258008]{margin-bottom:4px;text-align:center;line-height:1;display:flex;justify-content:space-around;z-index:5}.outer[data-v-78258008]{display:flex;margin:0 auto}.left_box[data-v-78258008]{display:flex;flex-direction:column;gap:4px;padding-top:82px;padding-right:2px}.left_box .left_contain[data-v-78258008]{display:grid;grid-template-columns:1fr 1fr 1fr;gap:4px}.left_box .left_contain>div[data-v-78258008]{box-sizing:border-box;width:175px;height:76px;cursor:pointer}.left_box .left_contain .info[data-v-78258008]{background-color:#2080f029;border-radius:3px;border:1px solid transparent;transition:all .3s;position:relative}.left_box .left_contain .info[data-v-78258008]:hover{background-color:#2080f038}.left_box .left_contain .info.true[data-v-78258008]{background-color:var(--n-color);border:1px solid rgb(32,128,240)}.left_box .left_contain .info .facility-name[data-v-78258008]{color:#2080f0}.left_box .left_contain .warning[data-v-78258008]{background-color:#f0a02029;border-radius:3px;border:1px solid transparent;transition:all .3s;position:relative}.left_box .left_contain .warning[data-v-78258008]:hover{background-color:#f0a02038}.left_box .left_contain .warning.true[data-v-78258008]{background-color:var(--n-color);border:1px solid rgb(240,160,32)}.left_box .left_contain .warning .facility-name[data-v-78258008]{color:#f0a020}.left_box .left_contain .primary[data-v-78258008]{background-color:#18a05829;border-radius:3px;border:1px solid transparent;transition:all .3s}.left_box .left_contain .primary[data-v-78258008]:hover{background-color:#18a05838}.left_box .left_contain .primary.true[data-v-78258008]{background-color:var(--n-color);border:1px solid rgb(24,160,88)}.left_box .left_contain .primary .facility-name[data-v-78258008]{color:#18a058}.mid_box[data-v-78258008]{display:flex;flex-direction:column}.waiting[data-v-78258008]{width:100%;height:100%;display:flex;align-items:center;justify-content:center;border:1px dashed rgb(51,54,57);opacity:.6;transition:all .3s;cursor:pointer;border-radius:3px}.waiting[data-v-78258008]:hover{opacity:1;border:1px dashed rgb(54,173,106);color:#36ad6a}.waiting div[data-v-78258008]{text-align:center}.draggable[data-v-78258008]{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center}.product-bg[data-v-78258008]{content:"";position:absolute;top:0;left:0;width:173px;height:74px;opacity:var(--7f05acbb);background-repeat:no-repeat;background-size:100%;background-position:110px -20px;z-index:3;pointer-events:none}.avatar-wrapper[data-v-78258008]{position:relative}.workaholic[data-v-78258008]{position:absolute;content:"";top:0;left:0;width:45px;height:45px;opacity:.35;background-color:red;pointer-events:none}.n-base-selection-placeholder .n-avatar{display:none}.n-table[data-v-d70a169d]{min-width:100%}.n-table th[data-v-d70a169d]{width:124px;box-sizing:border-box}.label[data-v-d70a169d]{display:flex;flex-direction:row;align-items:center;gap:6px}.dropdown-container{display:flex;align-items:center;margin-top:5px}.dropdown-label{flex:0 0 40%;max-width:125px}.dropdown-select{flex:1}.w-980[data-v-53621c35]{width:100%;max-width:980px}.mx-auto[data-v-53621c35]{margin:0 auto}.mt-12[data-v-53621c35]{margin-top:12px}.mb-12[data-v-53621c35]{margin-bottom:12px}.px-12[data-v-53621c35]{padding:0 12px}.mw-980[data-v-53621c35]{min-width:980px}.plan-bar[data-v-53621c35]{display:flex;flex-direction:row;flex-grow:0;gap:6px;padding:0 12px}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
h2[data-v-25048cec]{margin:0;font-size:1.2rem;text-align:center}.page-title[data-v-25048cec]{text-align:center;font-size:24px;margin-bottom:20px}.report-card[data-v-25048cec]{position:relative;background-color:var(--n-color);padding:10px 20px 16px;height:300px;box-sizing:border-box;border-radius:8px}.report-card-expand[data-v-25048cec]{position:absolute;width:calc(100% - 24px);height:calc(100% - 24px);top:12px;left:12px;box-sizing:border-box;z-index:9}.toggle[data-v-25048cec]{position:absolute;top:10px}.toggle-size[data-v-25048cec]{right:10px}.toggle-width[data-v-25048cec]{left:10px}.line-outer-container[data-v-25048cec]{width:100%;overflow-x:scroll;flex:1}.line-inner-container[data-v-25048cec]{padding:0 12px 16px;height:100%;box-sizing:border-box}
h2[data-v-a94ff07f]{margin:0;font-size:1.2rem;text-align:center}.page-title[data-v-a94ff07f]{text-align:center;font-size:24px;margin-bottom:20px}.report-card[data-v-a94ff07f]{position:relative;background-color:var(--n-color);padding:10px 20px 16px;height:300px;box-sizing:border-box;border-radius:8px}.report-card-expand[data-v-a94ff07f]{position:absolute;width:calc(100% - 24px);height:calc(100% - 24px);top:12px;left:12px;box-sizing:border-box;z-index:9}.toggle[data-v-a94ff07f]{position:absolute;top:10px}.toggle-size[data-v-a94ff07f]{right:10px}.toggle-width[data-v-a94ff07f]{left:10px}.line-outer-container[data-v-a94ff07f]{width:100%;overflow-x:scroll;flex:1}.line-inner-container[data-v-a94ff07f]{padding:0 12px 16px;height:100%;box-sizing:border-box}

View file

@ -1 +1 @@
import{u as N,C as V,a as j,L as D,T as L,b as P,P as R,c as O,p as H,d as I,e as T,f as F,A as q,g as J,h as X}from"./record.js";import{bm as w,br as Z,r as u,s as G,bC as y,by as d,bw as t,bv as s,bt as l,F as K,bD as Q,bu as v,bI as U,bE as W,bJ as Y,bo as p,aX as ee,b3 as te}from"./_plugin-vue_export-helper.js";import{b as oe,_ as ne}from"./Grid.js";import"./main.js";import"./get-slot.js";var M={};Object.defineProperty(M,"__esModule",{value:!0});const _=w,ae={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},se=(0,_.createStaticVNode)('<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4h4v4"></path><path d="M14 10l6-6"></path><path d="M8 20H4v-4"></path><path d="M4 20l6-6"></path></g>',1),le=[se];var re=M.default=(0,_.defineComponent)({name:"ArrowsDiagonal",render:function(r,i){return(0,_.openBlock)(),(0,_.createElementBlock)("svg",ae,le)}}),C={};Object.defineProperty(C,"__esModule",{value:!0});const m=w,ie={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},ce=(0,m.createStaticVNode)('<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 10h-4V6"></path><path d="M20 4l-6 6"></path><path d="M6 14h4v4"></path><path d="M10 14l-6 6"></path></g>',1),ue=[ce];var de=C.default=(0,m.defineComponent)({name:"ArrowsDiagonalMinimize2",render:function(r,i){return(0,m.openBlock)(),(0,m.createElementBlock)("svg",ie,ue)}}),$={};Object.defineProperty($,"__esModule",{value:!0});const o=w,pe={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},_e=(0,o.createElementVNode)("g",{fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[(0,o.createElementVNode)("path",{d:"M7 8l-4 4l4 4"}),(0,o.createElementVNode)("path",{d:"M17 8l4 4l-4 4"}),(0,o.createElementVNode)("path",{d:"M3 12h18"})],-1),me=[_e];var he=$.default=(0,o.defineComponent)({name:"ArrowsHorizontal",render:function(r,i){return(0,o.openBlock)(),(0,o.createElementBlock)("svg",pe,me)}});const ge={class:"line-outer-container"},ve={__name:"RecordLine",setup(h){const r=N(),{getMoodRatios:i}=r;V.register(j,D,L,P,R,O,H,I,T,F,q,J);const c=u(-1),e=u([]),g=u([]);G(async()=>{g.value=await i(),e.value=new Array(g.value.length).fill(100)});const B=u({responsive:!0,maintainAspectRatio:!1,scales:{x:{autoSkip:!0,type:"time",time:{unit:"day"}},y:{beginAtZero:!0,ticks:{min:0,max:24,stepSize:4}}},plugins:{datalabels:{display:!1}}});function S(n){e.value[n]==100?e.value[n]=300:e.value[n]==300?e.value[n]=700:e.value[n]=100}return(n,f)=>{const k=ee,b=te,E=ne,A=oe;return l(),y("div",null,[f[0]||(f[0]=d("h1",{class:"page-title"},"干员心情折线表",-1)),t(A,{"x-gap":12,"y-gap":8,collapsed:!1,cols:"1 s:1 m:2 l:3 xl:4 2xl:5",responsive:"screen"},{default:s(()=>[(l(!0),y(K,null,Q(g.value,(x,a)=>(l(),v(E,{key:a,class:U(["report-card",{"report-card-expand":c.value==a}])},{default:s(()=>[d("h2",null,W(x.groupName),1),d("div",ge,[d("div",{class:"line-inner-container",style:Y({width:e.value[a]+"%"})},[t(p(X),{data:x.moodData,options:B.value},null,8,["data","options"])],4)]),t(b,{class:"toggle toggle-size",size:"small",onClick:z=>c.value=c.value==-1?a:-1,focusable:!1},{icon:s(()=>[t(k,null,{default:s(()=>[c.value==a?(l(),v(p(de),{key:0})):(l(),v(p(re),{key:1}))]),_:2},1024)]),_:2},1032,["onClick"]),t(b,{class:"toggle toggle-width",size:"small",onClick:z=>S(a),focusable:!1},{icon:s(()=>[t(k,null,{default:s(()=>[t(p(he))]),_:1})]),_:2},1032,["onClick"])]),_:2},1032,["class"]))),128))]),_:1})])}}},ye=Z(ve,[["__scopeId","data-v-25048cec"]]);export{ye as default};
import{u as N,C as V,a as j,L as D,T as L,b as P,P as R,c as O,p as H,d as I,e as T,f as F,A as q,g as J,h as X}from"./record.js";import{bm as f,br as Z,r as u,s as G,bC as y,by as d,bw as t,bv as s,bt as l,F as K,bD as Q,bu as v,bI as U,bE as W,bJ as Y,bo as p,aX as ee,b3 as te}from"./_plugin-vue_export-helper.js";import{b as oe,_ as ne}from"./Grid.js";import"./main.js";import"./get-slot.js";var M={};Object.defineProperty(M,"__esModule",{value:!0});const _=f,ae={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},se=(0,_.createStaticVNode)('<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4h4v4"></path><path d="M14 10l6-6"></path><path d="M8 20H4v-4"></path><path d="M4 20l6-6"></path></g>',1),le=[se];var re=M.default=(0,_.defineComponent)({name:"ArrowsDiagonal",render:function(r,i){return(0,_.openBlock)(),(0,_.createElementBlock)("svg",ae,le)}}),C={};Object.defineProperty(C,"__esModule",{value:!0});const m=f,ie={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},ce=(0,m.createStaticVNode)('<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 10h-4V6"></path><path d="M20 4l-6 6"></path><path d="M6 14h4v4"></path><path d="M10 14l-6 6"></path></g>',1),ue=[ce];var de=C.default=(0,m.defineComponent)({name:"ArrowsDiagonalMinimize2",render:function(r,i){return(0,m.openBlock)(),(0,m.createElementBlock)("svg",ie,ue)}}),$={};Object.defineProperty($,"__esModule",{value:!0});const o=f,pe={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",viewBox:"0 0 24 24"},_e=(0,o.createElementVNode)("g",{fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[(0,o.createElementVNode)("path",{d:"M7 8l-4 4l4 4"}),(0,o.createElementVNode)("path",{d:"M17 8l4 4l-4 4"}),(0,o.createElementVNode)("path",{d:"M3 12h18"})],-1),me=[_e];var he=$.default=(0,o.defineComponent)({name:"ArrowsHorizontal",render:function(r,i){return(0,o.openBlock)(),(0,o.createElementBlock)("svg",pe,me)}});const ge={class:"line-outer-container"},ve={__name:"RecordLine",setup(h){const r=N(),{getMoodRatios:i}=r;V.register(j,D,L,P,R,O,H,I,T,F,q,J);const c=u(-1),e=u([]),g=u([]);G(async()=>{g.value=await i(),e.value=new Array(g.value.length).fill(100)});const B=u({responsive:!0,maintainAspectRatio:!1,scales:{x:{autoSkip:!0,type:"time",time:{unit:"day"}},y:{beginAtZero:!0,ticks:{min:0,max:24,stepSize:4}}},plugins:{datalabels:{display:!1}}});function S(n){e.value[n]==100?e.value[n]=300:e.value[n]==300?e.value[n]=700:e.value[n]=100}return(n,w)=>{const k=ee,b=te,E=ne,A=oe;return l(),y("div",null,[w[0]||(w[0]=d("h1",{class:"page-title"},"干员心情折线表",-1)),t(A,{"x-gap":12,"y-gap":8,collapsed:!1,cols:"1 s:1 m:2 l:3 xl:4 2xl:5",responsive:"screen"},{default:s(()=>[(l(!0),y(K,null,Q(g.value,(x,a)=>(l(),v(E,{key:a,class:U(["report-card",{"report-card-expand":c.value==a}])},{default:s(()=>[d("h2",null,W(x.groupName),1),d("div",ge,[d("div",{class:"line-inner-container",style:Y({width:e.value[a]+"%"})},[t(p(X),{data:x.moodData,options:B.value},null,8,["data","options"])],4)]),t(b,{class:"toggle toggle-size",size:"small",onClick:z=>c.value=c.value==-1?a:-1,focusable:!1},{icon:s(()=>[t(k,null,{default:s(()=>[c.value==a?(l(),v(p(de),{key:0})):(l(),v(p(re),{key:1}))]),_:2},1024)]),_:2},1032,["onClick"]),t(b,{class:"toggle toggle-width",size:"small",onClick:z=>S(a),focusable:!1},{icon:s(()=>[t(k,null,{default:s(()=>[t(p(he))]),_:1})]),_:2},1032,["onClick"])]),_:2},1032,["class"]))),128))]),_:1})])}}},ye=Z(ve,[["__scopeId","data-v-a94ff07f"]]);export{ye as default};

View file

@ -1 +1 @@
h2[data-v-f7ea91b8]{margin-bottom:10px;font-size:1.2rem;text-align:center}.page-title[data-v-f7ea91b8]{text-align:center;font-size:24px;margin-bottom:20px}
h2[data-v-2cc4b433]{margin-bottom:10px;font-size:1.2rem;text-align:center}.page-title[data-v-2cc4b433]{text-align:center;font-size:24px;margin-bottom:20px}

View file

@ -1 +1 @@
import{u as f,C as b,a as S,L as x,T as y,b as k,P as v,c as C,p as E,d as P,e as R,f as h,A as w,g as B,i as L}from"./record.js";import{br as D,r as l,s as M,bC as c,by as i,bw as p,bv as u,bt as n,F as N,bD as T,bu as A,bE as F,bo as V}from"./_plugin-vue_export-helper.js";import{b as I,_ as O}from"./Grid.js";import"./main.js";import"./get-slot.js";const j={__name:"RecordPie",setup(q){const _=f(),{getMoodRatios:d}=_;b.register(S,x,y,k,v,C,E,P,R,h,w,B);const r=l([]);M(async()=>{r.value=await d()});const m=l({plugins:{datalabels:{color:"black",formatter:function(a,t){let e=t.dataset.data.reduce((o,s)=>o+s,0);return console.log(a,e,a/e),Math.round(a/e*100)+"%"}},legend:{display:!1}}});return(a,t)=>{const e=O,o=I;return n(),c("div",null,[t[0]||(t[0]=i("h1",{class:"page-title"},"工作休息比例报表",-1)),p(o,{"x-gap":12,"y-gap":8,collapsed:!1,cols:"1 s:1 m:2 l:3 xl:4 2xl:5",responsive:"screen"},{default:u(()=>[(n(!0),c(N,null,T(r.value,(s,g)=>(n(),A(e,{key:g,class:"report-card"},{default:u(()=>[i("h2",null,F(s.groupName),1),p(V(L),{data:s.workRestData,options:m.value},null,8,["data","options"])]),_:2},1024))),128))]),_:1})])}}},Q=D(j,[["__scopeId","data-v-f7ea91b8"]]);export{Q as default};
import{u as b,C as f,a as S,L as x,T as y,b as k,P as v,c as C,p as E,d as P,e as R,f as h,A as w,g as B,i as L}from"./record.js";import{br as D,r as l,s as M,bC as c,by as i,bw as p,bv as u,bt as n,F as N,bD as T,bu as A,bE as F,bo as V}from"./_plugin-vue_export-helper.js";import{b as I,_ as O}from"./Grid.js";import"./main.js";import"./get-slot.js";const j={__name:"RecordPie",setup(q){const _=b(),{getMoodRatios:d}=_;f.register(S,x,y,k,v,C,E,P,R,h,w,B);const r=l([]);M(async()=>{r.value=await d()});const m=l({plugins:{datalabels:{color:"black",formatter:function(a,t){let e=t.dataset.data.reduce((o,s)=>o+s,0);return console.log(a,e,a/e),Math.round(a/e*100)+"%"}},legend:{display:!1}}});return(a,t)=>{const e=O,o=I;return n(),c("div",null,[t[0]||(t[0]=i("h1",{class:"page-title"},"工作休息比例报表",-1)),p(o,{"x-gap":12,"y-gap":8,collapsed:!1,cols:"1 s:1 m:2 l:3 xl:4 2xl:5",responsive:"screen"},{default:u(()=>[(n(!0),c(N,null,T(r.value,(s,g)=>(n(),A(e,{key:g,class:"report-card"},{default:u(()=>[i("h2",null,F(s.groupName),1),p(V(L),{data:s.workRestData,options:m.value},null,8,["data","options"])]),_:2},1024))),128))]),_:1})])}}},Q=D(j,[["__scopeId","data-v-2cc4b433"]]);export{Q as default};

View file

@ -1 +1 @@
@charset "UTF-8";.sss-container[data-v-ad4ed9f8]{display:flex;width:100%;gap:8px}.wrapper[data-v-ad4ed9f8]{white-space:pre-wrap;-webkit-user-select:text;user-select:text}.title[data-v-ad4ed9f8]{font-size:18px;font-weight:500;margin-bottom:6px}p[data-v-0f90c467]{margin:0 0 10px}.misc-container[data-v-0f90c467]{margin-top:12px;display:flex;align-items:center;gap:12px}.tasktable[data-v-1ccbc6a4]{margin-top:4px}.btn-clear[data-v-1ccbc6a4]{margin:4px}.tasktable table[data-v-1ccbc6a4]{width:100%}@media screen and (max-width: 1399px){.tasktable[data-v-1ccbc6a4]{height:300px;overflow-y:auto}.tasktable table[data-v-1ccbc6a4]{border-collapse:collapse}.tasktable td[data-v-1ccbc6a4]:first-child{width:10%}.tasktable td[data-v-1ccbc6a4]:nth-child(2){width:18%}.tasktable td[data-v-1ccbc6a4]:not(:first-child):not(:nth-child(2)){width:10.2857142857%}.tasktable thead[data-v-1ccbc6a4]{position:sticky;top:0;background-color:#7ea5b4;z-index:1}}@media screen and (min-width: 1400px){.tasktable[data-v-1ccbc6a4]{height:auto}.tasktable table[data-v-1ccbc6a4]{border-collapse:collapse}.tasktable td[data-v-1ccbc6a4]:first-child{width:10%}.tasktable td[data-v-1ccbc6a4]:nth-child(2){width:18%}.tasktable td[data-v-1ccbc6a4]:not(:first-child):not(:nth-child(2)){width:10.2857142857%}.tasktable thead[data-v-1ccbc6a4]{background-color:#7ea5b4}}.class1[data-v-1ccbc6a4]{background-color:var(--55e5587c);text-align:center;vertical-align:middle}.class2[data-v-1ccbc6a4]{background-color:var(--86e65da8);text-align:center;vertical-align:middle}.custom-tag[data-v-1ccbc6a4]{width:100%;height:100%;justify-content:space-between}.today[data-v-1ccbc6a4]{font-weight:400;font-size:12px}.activity[data-v-1ccbc6a4]{align-items:center}p[data-v-7e510649]{margin:0 0 8px}h4[data-v-7e510649]{margin:12px 0 10px}.big-table[data-v-7e510649]{margin-top:10px;max-width:320px}.big-table th[data-v-7e510649]{text-align:center}.big-table tr[data-v-7e510649]{width:70px}.big-table td[data-v-7e510649]{height:24px}.big-table td[data-v-7e510649]:nth-child(1){width:70px;text-align:center}.big-table td[data-v-7e510649]:nth-child(2){width:420px}.final[data-v-7e510649]{margin:16px 0 0}p[data-v-8fd7d6cc]{margin:2px 0}h4[data-v-8fd7d6cc]{margin:12px 0 8px}table[data-v-8fd7d6cc]{width:100%}td[data-v-8fd7d6cc]:nth-child(1){width:80px}.ignore-blacklist[data-v-8fd7d6cc]{margin-bottom:10px;display:flex;gap:12px}.h4[data-v-8fd7d6cc]{font-size:16px;font-weight:500}.maa-shop[data-v-8fd7d6cc]{margin:8px 0}.item[data-v-8fd7d6cc]{font-weight:500;font-size:16px}.email-title[data-v-c5308ada]{width:100%}.expand[data-v-c5308ada]{flex-grow:1}.email-table[data-v-c5308ada]{width:100%;margin-bottom:12px}.email-test[data-v-c5308ada]{display:flex;align-items:center;gap:16px}.email-mode[data-v-c5308ada]{margin-left:20px}.email-label[data-v-c5308ada]{width:68px}p[data-v-c5308ada]{margin:0 0 10px}.mt-16[data-v-c5308ada]{margin-top:16px}.item[data-v-90373ea0]{font-weight:500;font-size:16px}.n-divider[data-v-90373ea0]:not(.n-divider--vertical){margin:6px 0}.misc-container{margin-top:12px;display:flex;align-items:center;gap:12px}.threshold[data-v-12e92dd2]{display:flex;align-items:center;gap:14px;width:100%}.mower-basic[data-v-12e92dd2]{width:100%}.mower-basic td[data-v-12e92dd2]:nth-child(1){width:120px}.mower-basic td[data-v-12e92dd2]:nth-child(3){padding-left:6px;width:40px}.riic-conf[data-v-12e92dd2]{width:100%}.riic-conf td[data-v-12e92dd2]:nth-child(1){width:130px}.riic-conf td[data-v-12e92dd2]:nth-child(3){padding-left:12px;width:120px}.coord td[data-v-12e92dd2]{width:120px}.coord td[data-v-12e92dd2]:nth-child(1),.coord td[data-v-12e92dd2]:nth-child(3){width:30px}.coord td[data-v-12e92dd2]:nth-child(2){padding-right:30px}.coord-label[data-v-12e92dd2]{width:40px;padding-left:8px}p[data-v-12e92dd2]{margin:0 0 8px}h4[data-v-12e92dd2]{margin:12px 0 10px}.time-table[data-v-12e92dd2]{width:100%;margin-bottom:12px}.time-table td[data-v-12e92dd2]:nth-child(1){width:40px}.scale[data-v-12e92dd2]{width:60px;text-align:right}.scale-apply[data-v-12e92dd2]{margin-left:24px}.waiting-table th[data-v-12e92dd2],.waiting-table td[data-v-12e92dd2]{padding:4px;min-width:70px;width:100px}.waiting-table th[data-v-12e92dd2]:first-child,.waiting-table td[data-v-12e92dd2]:first-child{width:auto;padding:4px 8px}@media (max-width: 1399px){.grid-two{margin:0 0 -10px;width:100%;max-width:600px}.grid-left{display:grid;row-gap:10px;grid-template-columns:100%}.grid-right{display:grid;row-gap:10px;grid-template-columns:100%;margin-top:10px}}@media (min-width: 1400px){.grid-two{display:grid;grid-template-columns:minmax(0px,1fr) minmax(0px,1fr);align-items:flex-start;gap:5px}.grid-left,.grid-right{display:grid;gap:5px;grid-template-columns:100%;max-width:600px}}.n-divider:not(.n-divider--vertical){margin:14px 0 8px}
@charset "UTF-8";.sss-container[data-v-19f9e9b9]{display:flex;width:100%;gap:8px}.wrapper[data-v-19f9e9b9]{white-space:pre-wrap;-webkit-user-select:text;user-select:text}.title[data-v-19f9e9b9]{font-size:18px;font-weight:500;margin-bottom:6px}p[data-v-666d3ffa]{margin:0 0 10px}.misc-container[data-v-666d3ffa]{margin-top:12px;display:flex;align-items:center;gap:12px}.tasktable[data-v-4a926094]{margin-top:4px}.btn-clear[data-v-4a926094]{margin:4px}.tasktable table[data-v-4a926094]{width:100%}@media screen and (max-width: 1399px){.tasktable[data-v-4a926094]{height:300px;overflow-y:auto}.tasktable table[data-v-4a926094]{border-collapse:collapse}.tasktable td[data-v-4a926094]:first-child{width:10%}.tasktable td[data-v-4a926094]:nth-child(2){width:18%}.tasktable td[data-v-4a926094]:not(:first-child):not(:nth-child(2)){width:10.2857142857%}.tasktable thead[data-v-4a926094]{position:sticky;top:0;background-color:#7ea5b4;z-index:1}}@media screen and (min-width: 1400px){.tasktable[data-v-4a926094]{height:auto}.tasktable table[data-v-4a926094]{border-collapse:collapse}.tasktable td[data-v-4a926094]:first-child{width:10%}.tasktable td[data-v-4a926094]:nth-child(2){width:18%}.tasktable td[data-v-4a926094]:not(:first-child):not(:nth-child(2)){width:10.2857142857%}.tasktable thead[data-v-4a926094]{background-color:#7ea5b4}}.class1[data-v-4a926094]{background-color:var(--6c3102f4);text-align:center;vertical-align:middle}.class2[data-v-4a926094]{background-color:var(--7a203de8);text-align:center;vertical-align:middle}.custom-tag[data-v-4a926094]{width:100%;height:100%;justify-content:space-between}.today[data-v-4a926094]{font-weight:400;font-size:12px}.activity[data-v-4a926094]{align-items:center}p[data-v-c062d730]{margin:0 0 8px}h4[data-v-c062d730]{margin:12px 0 10px}.big-table[data-v-c062d730]{margin-top:10px;max-width:320px}.big-table th[data-v-c062d730]{text-align:center}.big-table tr[data-v-c062d730]{width:70px}.big-table td[data-v-c062d730]{height:24px}.big-table td[data-v-c062d730]:nth-child(1){width:70px;text-align:center}.big-table td[data-v-c062d730]:nth-child(2){width:420px}.final[data-v-c062d730]{margin:16px 0 0}p[data-v-72c0637f]{margin:2px 0}h4[data-v-72c0637f]{margin:12px 0 8px}table[data-v-72c0637f]{width:100%}td[data-v-72c0637f]:nth-child(1){width:80px}.ignore-blacklist[data-v-72c0637f]{margin-bottom:10px;display:flex;gap:12px}.h4[data-v-72c0637f]{font-size:16px;font-weight:500}.maa-shop[data-v-72c0637f]{margin:8px 0}.item[data-v-72c0637f]{font-weight:500;font-size:16px}.email-title[data-v-9528d27c]{width:100%}.expand[data-v-9528d27c]{flex-grow:1}.email-table[data-v-9528d27c]{width:100%;margin-bottom:12px}.email-test[data-v-9528d27c]{display:flex;align-items:center;gap:16px}.email-mode[data-v-9528d27c]{margin-left:20px}.email-label[data-v-9528d27c]{width:68px}p[data-v-9528d27c]{margin:0 0 10px}.mt-16[data-v-9528d27c]{margin-top:16px}.item[data-v-65920527]{font-weight:500;font-size:16px}.n-divider[data-v-65920527]:not(.n-divider--vertical){margin:6px 0}.misc-container{margin-top:12px;display:flex;align-items:center;gap:12px}.threshold[data-v-cae6351e]{display:flex;align-items:center;gap:14px;width:100%}.mower-basic[data-v-cae6351e]{width:100%}.mower-basic td[data-v-cae6351e]:nth-child(1){width:120px}.mower-basic td[data-v-cae6351e]:nth-child(3){padding-left:6px;width:40px}.riic-conf[data-v-cae6351e]{width:100%}.riic-conf td[data-v-cae6351e]:nth-child(1){width:130px}.riic-conf td[data-v-cae6351e]:nth-child(3){padding-left:12px;width:120px}.coord td[data-v-cae6351e]{width:120px}.coord td[data-v-cae6351e]:nth-child(1),.coord td[data-v-cae6351e]:nth-child(3){width:30px}.coord td[data-v-cae6351e]:nth-child(2){padding-right:30px}.coord-label[data-v-cae6351e]{width:40px;padding-left:8px}p[data-v-cae6351e]{margin:0 0 8px}h4[data-v-cae6351e]{margin:12px 0 10px}.time-table[data-v-cae6351e]{width:100%;margin-bottom:12px}.time-table td[data-v-cae6351e]:nth-child(1){width:40px}.scale[data-v-cae6351e]{width:60px;text-align:right}.scale-apply[data-v-cae6351e]{margin-left:24px}.waiting-table th[data-v-cae6351e],.waiting-table td[data-v-cae6351e]{padding:4px;min-width:70px;width:100px}.waiting-table th[data-v-cae6351e]:first-child,.waiting-table td[data-v-cae6351e]:first-child{width:auto;padding:4px 8px}@media (max-width: 1399px){.grid-two{margin:0 0 -10px;width:100%;max-width:600px}.grid-left{display:grid;row-gap:10px;grid-template-columns:100%}.grid-right{display:grid;row-gap:10px;grid-template-columns:100%;margin-top:10px}}@media (min-width: 1400px){.grid-two{display:grid;grid-template-columns:minmax(0px,1fr) minmax(0px,1fr);align-items:flex-start;gap:5px}.grid-left,.grid-right{display:grid;gap:5px;grid-template-columns:100%;max-width:600px}}.n-divider:not(.n-divider--vertical){margin:14px 0 8px}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.width100[data-v-49c0eae3]{width:100%}
.width100[data-v-b1322d95]{width:100%}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
@charset "UTF-8";.n-avatar,.img{pointer-events:none!important}.tabs[data-v-46334205],.provider[data-v-46334205],.layout-container[data-v-46334205]{height:100%}#app{height:var(--app-height, 100vh);width:var(--app-width, 100vw);transform-origin:0 0}.n-tab-pane{flex-grow:1;display:flex;flex-direction:column;overflow:auto}.n-card-header__main{display:flex;align-items:center;gap:6px}td{height:34px}.table-space{padding-right:20px}.external-container{max-width:600px;margin:0 auto}.n-checkbox{align-items:center}.n-form-item{margin-top:12px}.n-form-item:first-child{margin-top:0}.dialog-btn{margin-left:4px}.report-card{display:flex;flex-direction:column;align-items:center;justify-content:center;width:300px;height:200px;padding:20px 20px 80px;border:1px solid #ccc;box-shadow:0 2px 4px #0000001a}.n-checkbox .n-checkbox__label{flex-grow:1;display:flex;align-items:center;padding-right:0}.outer-layout{height:100%}.outer-layout>.n-layout-scroll-container{display:flex;flex-direction:column;height:100%;overflow:hidden}.layout-content-container>.n-layout-scroll-container{width:100%;height:100%;display:flex;flex-direction:column;overflow:auto;gap:8px;align-items:center}.home-container{padding:12px;flex-grow:1;display:flex;flex-direction:column;gap:8px;width:calc(100% - 24px);height:calc(100% - 24px);position:relative}pre{word-break:break-all!important;font-family:Cascadia Mono,Consolas,Microsoft YaHei,SF Mono,Menlo,PingFang SC,monospace!important}.n-dynamic-input-item__action{align-self:center!important}ul,ol{padding-left:18px;margin:0}.card-title{font-weight:500;font-size:18px;white-space:nowrap}
@charset "UTF-8";.n-avatar,.img{pointer-events:none!important}.tabs[data-v-a37af22d],.provider[data-v-a37af22d],.layout-container[data-v-a37af22d]{height:100%}#app{height:var(--app-height, 100vh);width:var(--app-width, 100vw);transform-origin:0 0}.n-tab-pane{flex-grow:1;display:flex;flex-direction:column;overflow:auto}.n-card-header__main{display:flex;align-items:center;gap:6px}td{height:34px}.table-space{padding-right:20px}.external-container{max-width:600px;margin:0 auto}.n-checkbox{align-items:center}.n-form-item{margin-top:12px}.n-form-item:first-child{margin-top:0}.dialog-btn{margin-left:4px}.report-card{display:flex;flex-direction:column;align-items:center;justify-content:center;width:300px;height:200px;padding:20px 20px 80px;border:1px solid #ccc;box-shadow:0 2px 4px #0000001a}.n-checkbox .n-checkbox__label{flex-grow:1;display:flex;align-items:center;padding-right:0}.outer-layout{height:100%}.outer-layout>.n-layout-scroll-container{display:flex;flex-direction:column;height:100%;overflow:hidden}.layout-content-container>.n-layout-scroll-container{width:100%;height:100%;display:flex;flex-direction:column;overflow:auto;gap:8px;align-items:center}.home-container{padding:12px;flex-grow:1;display:flex;flex-direction:column;gap:8px;width:calc(100% - 24px);height:calc(100% - 24px);position:relative}pre{word-break:break-all!important;font-family:Cascadia Mono,Consolas,Microsoft YaHei,SF Mono,Menlo,PingFang SC,monospace!important}.n-dynamic-input-item__action{align-self:center!important}ul,ol{padding-left:18px;margin:0}.card-title{font-weight:500;font-size:18px;white-space:nowrap}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.mower-list[data-v-4602b0dd]{box-sizing:border-box;width:100vw;padding:12px;display:flex;flex-direction:column;gap:8px}.header[data-v-4602b0dd]{display:flex;gap:6px;align-items:center;height:28px}.expand[data-v-4602b0dd]{flex-grow:1}.folder[data-v-4602b0dd]{display:flex;gap:6px;align-items:center}.folder-content[data-v-4602b0dd]{word-break:break-all}
.mower-list[data-v-50f5626a]{box-sizing:border-box;width:100vw;padding:12px;display:flex;flex-direction:column;gap:8px}.header[data-v-50f5626a]{display:flex;gap:6px;align-items:center;height:28px}.expand[data-v-50f5626a]{flex-grow:1}.folder[data-v-50f5626a]{display:flex;gap:6px;align-items:center}.folder-content[data-v-50f5626a]{word-break:break-all}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.readme[data-v-dae6ad05]{word-break:break-all;max-width:800px}
.readme[data-v-25ca14dd]{word-break:break-all;max-width:800px}

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
.chart[data-v-c00d84c9]{height:400px}.report-card_1[data-v-c00d84c9]{display:gird;flex-direction:column;align-items:center;justify-content:center;width:800px;height:400px;padding:20px 20px 80px;border:1px solid #ccc}
.chart[data-v-1e64842f]{height:400px}.report-card_1[data-v-1e64842f]{display:gird;flex-direction:column;align-items:center;justify-content:center;width:800px;height:400px;padding:20px 20px 80px;border:1px solid #ccc}

View file

@ -107,4 +107,4 @@ PERFORMANCE OF THIS SOFTWARE.
${p[2].marker} <span style="font-size:14px">${p[2].seriesName}:${p[0].data.龙门币订单}</span> <br>
${p[1].marker} <span style="font-size:14px">${p[1].seriesName}:${p[0].data.作战录像}</span> <br>
</div>`}},dataset:{dimensions:["","","",""],source:f.value},yAxis:{type:"category",axisPointer:{type:"shadow"},axisTick:{show:!1}},xAxis:{axisLabel:{formatter:function(p){return Math.abs(p)},scale:!0}},series:[{name:"",type:"bar",color:"#f5744f",position:"inside",label:{show:!0,formatter:function(p){if(p.value.===0)return""}},emphasis:{focus:"series"}},{name:"",type:"bar",stack:"Total",color:"#f3e28f",position:"inside",label:{show:!0,formatter:function(p){if(p.value.===0)return"";if(p.value.<0)return-p.value.}},emphasis:{focus:"series"}},{name:"",type:"bar",stack:"Total",color:"#64bfec",label:{show:!0,formatter:function(p){if(p.value.===0)return"";if(p.value.<0)return-p.value.}},emphasis:{focus:"series"}}]})),c=be(()=>({title:[{text:""}],legend:{data:["","",""],selected:{:!0,:!0}},dataZoom:{show:!1,type:"slider",realtime:!0,startValue:f.value.length-7,endValue:f.value.length,xAxisIndex:[0],bottom:"10",left:"30",height:10,borderColor:"rgba(0,0,0,0)",textStyle:{color:"#05D5FF"}},toolbox:{feature:{dataView:{show:!1,readOnly:!1},magicType:{show:!0,type:["line","bar"]},restore:{show:!0},saveAsImage:{show:!0,backgroundColor:"#FFFFFF"}}},tooltip:{trigger:"axis",axisPointer:{type:"cross",crossStyle:{color:"#999"}}},dataset:{dimensions:["","","",""],source:f.value},xAxis:{type:"category",axisPointer:{type:"shadow"}},yAxis:[{type:"value",axisLine:{show:!0,symbol:["none","path://M5,20 L5,5 L8,8 L5,2 L2,8 L5,5 L5.3,6 L5.3,20 "],symbolOffset:10,symbolSize:[35,38]},axisLabel:{formatter:"{value}"}},{type:"value",axisLabel:{formatter:"{value}"}}],series:[{name:"",type:"bar",yAxisIndex:0,color:"#f5744f",tooltip:{valueFormatter:function(p){return p}}},{name:"",type:"bar",yAxisIndex:0,color:"#64bfec",tooltip:{valueFormatter:function(p){return p}}},{name:"",type:"line",yAxisIndex:1,tooltip:{valueFormatter:function(p){return p}}}]})),d=be(()=>({title:[{text:""}],legend:{data:["",""],selected:{:!0,:!1}},toolbox:{feature:{dataView:{show:!1,readOnly:!1},magicType:{show:!0,type:["line","bar"]},restore:{show:!0},saveAsImage:{show:!0,backgroundColor:"#FFFFFF"}}},tooltip:{trigger:"axis",axisPointer:{type:"cross",crossStyle:{color:"#999"}}},dataset:{dimensions:["","",""],source:h.value},xAxis:{type:"category",axisPointer:{type:"shadow"}},yAxis:[{type:"value",axisLine:{show:!0,symbol:["none","path://M5,20 L5,5 L8,8 L5,2 L2,8 L5,5 L5.3,6 L5.3,20 "],symbolOffset:10,symbolSize:[35,38]},axisLabel:{formatter:"{value}"}},{type:"value",axisLine:{show:!0},position:"right"}],series:[{type:"line",yAxisIndex:0,color:"#faf0b5",tooltip:{valueFormatter:function(p){return p}}},{type:"bar",yAxisIndex:1,color:"#e70000",tooltip:{valueFormatter:function(p){return p}}}]}));return(p,g)=>{const y=g_,m=j_,_=X_,b=$_;return ln(),O_(N_,null,[jt("div",null,[jt("h1",cR,[g[1]||(g[1]=B_(" ")),sn(y,null,{default:ci(()=>g[0]||(g[0]=[jt("p",null,"tmpreport.csv",-1),jt("p",null,"",-1),jt("p",null,"report.csvmower",-1)])),_:1})])]),u.value?(ln(),Aa(m,{key:0,title:"",type:"error"},{default:ci(()=>g[2]||(g[2]=[jt("p",null,"tmpreport.csv",-1),jt("p",null,"",-1),jt("p",null,"report.csvmower",-1)])),_:1})):Da("",!0),jt("div",null,[sn(b,{"x-gap":"12","y-gap":"12",cols:"1 1000:2 ",style:{"text-align":"center"},autoresize:""},{default:ci(()=>[o.value?(ln(),Aa(_,{key:0},{default:ci(()=>[jt("div",vR,[sn(_o(wu),{class:"chart",option:v.value},null,8,["option"])])]),_:1})):Da("",!0),o.value?(ln(),Aa(_,{key:1},{default:ci(()=>[jt("div",dR,[sn(_o(wu),{class:"chart",option:c.value},null,8,["option"])])]),_:1})):Da("",!0),s.value?(ln(),Aa(_,{key:2},{default:ci(()=>[jt("div",pR,[sn(_o(wu),{class:"chart",option:d.value},null,8,["option"])])]),_:1})):Da("",!0)]),_:1})])],64)}}},xR=k_(gR,[["__scopeId","data-v-c00d84c9"]]);export{xR as default};
</div>`}},dataset:{dimensions:["","","",""],source:f.value},yAxis:{type:"category",axisPointer:{type:"shadow"},axisTick:{show:!1}},xAxis:{axisLabel:{formatter:function(p){return Math.abs(p)},scale:!0}},series:[{name:"",type:"bar",color:"#f5744f",position:"inside",label:{show:!0,formatter:function(p){if(p.value.===0)return""}},emphasis:{focus:"series"}},{name:"",type:"bar",stack:"Total",color:"#f3e28f",position:"inside",label:{show:!0,formatter:function(p){if(p.value.===0)return"";if(p.value.<0)return-p.value.}},emphasis:{focus:"series"}},{name:"",type:"bar",stack:"Total",color:"#64bfec",label:{show:!0,formatter:function(p){if(p.value.===0)return"";if(p.value.<0)return-p.value.}},emphasis:{focus:"series"}}]})),c=be(()=>({title:[{text:""}],legend:{data:["","",""],selected:{:!0,:!0}},dataZoom:{show:!1,type:"slider",realtime:!0,startValue:f.value.length-7,endValue:f.value.length,xAxisIndex:[0],bottom:"10",left:"30",height:10,borderColor:"rgba(0,0,0,0)",textStyle:{color:"#05D5FF"}},toolbox:{feature:{dataView:{show:!1,readOnly:!1},magicType:{show:!0,type:["line","bar"]},restore:{show:!0},saveAsImage:{show:!0,backgroundColor:"#FFFFFF"}}},tooltip:{trigger:"axis",axisPointer:{type:"cross",crossStyle:{color:"#999"}}},dataset:{dimensions:["","","",""],source:f.value},xAxis:{type:"category",axisPointer:{type:"shadow"}},yAxis:[{type:"value",axisLine:{show:!0,symbol:["none","path://M5,20 L5,5 L8,8 L5,2 L2,8 L5,5 L5.3,6 L5.3,20 "],symbolOffset:10,symbolSize:[35,38]},axisLabel:{formatter:"{value}"}},{type:"value",axisLabel:{formatter:"{value}"}}],series:[{name:"",type:"bar",yAxisIndex:0,color:"#f5744f",tooltip:{valueFormatter:function(p){return p}}},{name:"",type:"bar",yAxisIndex:0,color:"#64bfec",tooltip:{valueFormatter:function(p){return p}}},{name:"",type:"line",yAxisIndex:1,tooltip:{valueFormatter:function(p){return p}}}]})),d=be(()=>({title:[{text:""}],legend:{data:["",""],selected:{:!0,:!1}},toolbox:{feature:{dataView:{show:!1,readOnly:!1},magicType:{show:!0,type:["line","bar"]},restore:{show:!0},saveAsImage:{show:!0,backgroundColor:"#FFFFFF"}}},tooltip:{trigger:"axis",axisPointer:{type:"cross",crossStyle:{color:"#999"}}},dataset:{dimensions:["","",""],source:h.value},xAxis:{type:"category",axisPointer:{type:"shadow"}},yAxis:[{type:"value",axisLine:{show:!0,symbol:["none","path://M5,20 L5,5 L8,8 L5,2 L2,8 L5,5 L5.3,6 L5.3,20 "],symbolOffset:10,symbolSize:[35,38]},axisLabel:{formatter:"{value}"}},{type:"value",axisLine:{show:!0},position:"right"}],series:[{type:"line",yAxisIndex:0,color:"#faf0b5",tooltip:{valueFormatter:function(p){return p}}},{type:"bar",yAxisIndex:1,color:"#e70000",tooltip:{valueFormatter:function(p){return p}}}]}));return(p,g)=>{const y=g_,m=j_,_=X_,b=$_;return ln(),O_(N_,null,[jt("div",null,[jt("h1",cR,[g[1]||(g[1]=B_(" ")),sn(y,null,{default:ci(()=>g[0]||(g[0]=[jt("p",null,"tmpreport.csv",-1),jt("p",null,"",-1),jt("p",null,"report.csvmower",-1)])),_:1})])]),u.value?(ln(),Aa(m,{key:0,title:"",type:"error"},{default:ci(()=>g[2]||(g[2]=[jt("p",null,"tmpreport.csv",-1),jt("p",null,"",-1),jt("p",null,"report.csvmower",-1)])),_:1})):Da("",!0),jt("div",null,[sn(b,{"x-gap":"12","y-gap":"12",cols:"1 1000:2 ",style:{"text-align":"center"},autoresize:""},{default:ci(()=>[o.value?(ln(),Aa(_,{key:0},{default:ci(()=>[jt("div",vR,[sn(_o(wu),{class:"chart",option:v.value},null,8,["option"])])]),_:1})):Da("",!0),o.value?(ln(),Aa(_,{key:1},{default:ci(()=>[jt("div",dR,[sn(_o(wu),{class:"chart",option:c.value},null,8,["option"])])]),_:1})):Da("",!0),s.value?(ln(),Aa(_,{key:2},{default:ci(()=>[jt("div",pR,[sn(_o(wu),{class:"chart",option:d.value},null,8,["option"])])]),_:1})):Da("",!0)]),_:1})])],64)}}},xR=k_(gR,[["__scopeId","data-v-1e64842f"]]);export{xR as default};

BIN
ui/dist/avatar/凯瑟琳.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/avatar/波卜.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/avatar/维娜·维多利亚.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/building_skill/bskill_dorm_unfull.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/building_skill/bskill_ws_cost.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/building_skill/bskill_ws_p7.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/building_skill/trade_ord_spd&par1.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/building_skill/trade_ord_spd&par2.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/depot/凯瑟琳的信物.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/depot/未致蒙尘寻访凭证.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/depot/波卜的信物.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

BIN
ui/dist/depot/维娜·维多利亚的信物.webp (Stored with Git LFS) vendored Normal file

Binary file not shown.

24
ui/dist/index.html vendored
View file

@ -1,15 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mower WebUI in Browser</title>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mower WebUI in Browser</title>
<script type="module" crossorigin src="/assets/main.js"></script>
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper.js">
<link rel="stylesheet" crossorigin href="/assets/main.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
</head>
<body>
<div id="app"></div>
</body>
</html>

View file

@ -1,18 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mower Manager</title>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mower Manager</title>
<script type="module" crossorigin src="/assets/manager.js"></script>
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper.js">
<link rel="modulepreload" crossorigin href="/assets/Play.js">
<link rel="modulepreload" crossorigin href="/assets/TrashOutline.js">
<link rel="modulepreload" crossorigin href="/assets/Input.js">
<link rel="stylesheet" crossorigin href="/assets/manager.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
</head>
<body>
<div id="app"></div>
</body>
</html>

BIN
ui/public/avatar/凯瑟琳.webp (Stored with Git LFS) Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more