Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bot/base/localization.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ class LocalizationMap:
localization_map = {attr: value for attr, value in vars(LocalizationMap).items()
if not callable(value) and not attr.startswith('_')}

localization_map.update({
'True': '是',
'False': '否'
})

def _localization_single(string):
for name, value in localization_map.items():
string = string.replace(name, value)
Expand Down
5 changes: 4 additions & 1 deletion bot/base/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ def emit(self, record):

def get_task_log(self, task_id):
with self.lock:
logs = list(self.buffer[task_id])
if task_id in self.buffer:
logs = list(self.buffer[task_id])
else:
logs = []
return logs

task_log_handler = TaskLogHandler()
Expand Down
4 changes: 3 additions & 1 deletion module/umamusume/asset/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
AOHARUHAI_RACE_INRACE = UI("AOHARUHAI_RACE_INRACE", [template.UI_AOHARUHAI_RACE_INRACE], [])
AOHARUHAI_RACE_END = UI("AOHARUHAI_RACE_END", [template.UI_AOHARUHAI_RACE_END], [])
AOHARUHAI_RACE_SCHEDULE = UI("AOHARUHAI_RACE_SCHEDULE", [template.UI_AOHARUHAI_RACE_SCHEDULE], [])
AOHARUHAI_RACE_FINAL_START = UI("AOHARUHAI_RACE_FINAL_START", [template.UI_AOHARUHAI_RACE_FINAL_START], [])
AOHARUHAI_RACE_SELECT_OPPONENT = UI("AOHARUHAI_RACE_SELECT_OPPONENT", [template.UI_AOHARUHAI_RACE_SELECT_OPPONENT], [])


CULTIVATE_RACE_LIST = UI("CULTIVATE_RACE_LIST", [template.UI_CULTIVATE_RACE_LIST_1, template.UI_CULTIVATE_RACE_LIST_2], [])
Expand Down Expand Up @@ -73,7 +75,7 @@
CULTIVATE_SUPPORT_CARD_SELECT, CULTIVATE_FOLLOW_SUPPORT_CARD_SELECT, CULTIVATE_FINAL_CHECK, INFO,
CULTIVATE_MAIN_MENU, CULTIVATE_TRAINING_SELECT, CULTIVATE_EXTEND, CULTIVATE_CATCH_DOLL_GAME,
CULTIVATE_CATCH_DOLL_GAME_RESULT, CULTIVATE_LEVEL_RESULT,
AOHARUHAI_RACE, AOHARUHAI_RACE_INRACE, AOHARUHAI_RACE_END, AOHARUHAI_RACE_SCHEDULE,
AOHARUHAI_RACE_FINAL_START, AOHARUHAI_RACE_SELECT_OPPONENT, AOHARUHAI_RACE, AOHARUHAI_RACE_INRACE, AOHARUHAI_RACE_END, AOHARUHAI_RACE_SCHEDULE,
CULTIVATE_GOAL_RACE, CULTIVATE_RACE_LIST, CULTIVATE_RESULT, CULTIVATE_RESULT_1, CULTIVATE_RESULT_2,
CULTIVATE_LEARN_SKILL, RECEIVE_CUP,
CULTIVATE_URA_RACE_1, CULTIVATE_URA_RACE_2,CULTIVATE_URA_RACE_3,
Expand Down
2 changes: 1 addition & 1 deletion module/umamusume/hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def after_hook(ctx: UmamusumeContext):
if ctx.cultivate_detail and ctx.cultivate_detail.turn_info is not None:
if ctx.cultivate_detail.turn_info.parse_train_info_finish and ctx.cultivate_detail.turn_info.parse_main_menu_finish:
if not ctx.cultivate_detail.turn_info.turn_info_logged:
ctx.cultivate_detail.turn_info.log_turn_info()
ctx.cultivate_detail.turn_info.log_turn_info(ctx.task.detail.scenario)
ctx.cultivate_detail.turn_info.turn_info_logged = True
if ctx.cultivate_detail.turn_info.turn_operation is None:
ctx.cultivate_detail.turn_info.turn_operation = get_operation(ctx)
Expand Down
2 changes: 2 additions & 0 deletions module/umamusume/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
CULTIVATE_EVENT_UMAMUSUME: script_cultivate_event,
CULTIVATE_EVENT_SUPPORT_CARD: script_cultivate_event,
CULTIVATE_EVENT_SCENARIO: script_cultivate_event,
AOHARUHAI_RACE_FINAL_START: script_aoharuhai_race_final_start,
AOHARUHAI_RACE_SELECT_OPPONENT: script_aoharuhai_race_select_oponent,
AOHARUHAI_RACE: script_aoharuhai_race,
AOHARUHAI_RACE_INRACE: script_aoharuhai_race_inrace,
AOHARUHAI_RACE_END: script_aoharuhai_race_end,
Expand Down
128 changes: 110 additions & 18 deletions module/umamusume/scenario/aoharuhai_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def scenario_name(self) -> str:
return "青春杯"

def get_date_img(self, img: any) -> any:
return img[40:70, 160:280]
return img[40:70, 160:370]

def get_turn_to_race_img(self, img) -> any:
return img[70:120, 30:90]
Expand Down Expand Up @@ -98,18 +98,21 @@ def parse_training_result(self, img: any) -> list[int]:
skill_point_incr = (0 if skill_point_incr_text == "" else int(skill_point_incr_text)) + (0 if skill_point_incr_extra_text == "" else int(skill_point_incr_extra_text))

return [speed_icr, stamina_incr, power_incr, will_incr, intelligence_incr, skill_point_incr]

def parse_training_support_cord(self, img: any) -> list[SupportCardInfo]:
# TODO: 目前没有识别青春杯参数和青春杯友情条, 也没有将其作为训练权重的一部分,
base_x = 590

def parse_training_support_card(self, img: any) -> list[SupportCardInfo]:
base_x = 550
base_y = 177
inc = 115
support_card_list_info_result: list[SupportCardInfo] = []
for i in range(5):
support_card_icon = img[base_y:base_y + inc, base_x: base_x + 105]
support_card_icon = img[base_y:base_y + inc, base_x: base_x + 145]

# 有青春杯训练, 且青春杯友情未满
can_incr_aoharu_train = detect_aoharu_train_arrow(support_card_icon) and aoharu_train_not_full(support_card_icon)

# 判断好感度
support_card_icon = cv2.cvtColor(support_card_icon, cv2.COLOR_BGR2RGB)
favor_process_check_list = [support_card_icon[106, 16], support_card_icon[106, 20]]
favor_process_check_list = [support_card_icon[106, 56], support_card_icon[106, 60]]
support_card_favor_process = SupportCardFavorLevel.SUPPORT_CARD_FAVOR_LEVEL_UNKNOWN
for support_card_favor_process_pos in favor_process_check_list:
if compare_color_equal(support_card_favor_process_pos, [255, 235, 120]):
Expand All @@ -124,13 +127,6 @@ def parse_training_support_cord(self, img: any) -> list[SupportCardInfo]:
if support_card_favor_process != SupportCardFavorLevel.SUPPORT_CARD_FAVOR_LEVEL_UNKNOWN:
break

# 判断是否有事件
support_card_event_pos = support_card_icon[5, 83]
support_card_event_available = False
if (support_card_event_pos[0] >= 250
and 55 <= support_card_event_pos[1] <= 90
and 115 <= support_card_event_pos[2] <= 150):
support_card_event_available = True
# 判断支援卡类型
support_card_type = SupportCardType.SUPPORT_CARD_TYPE_UNKNOWN
support_card_icon = cv2.cvtColor(support_card_icon, cv2.COLOR_RGB2GRAY)
Expand All @@ -146,11 +142,107 @@ def parse_training_support_cord(self, img: any) -> list[SupportCardInfo]:
support_card_type = SupportCardType.SUPPORT_CARD_TYPE_INTELLIGENCE
elif image_match(support_card_icon, REF_SUPPORT_CARD_TYPE_FRIEND).find_match:
support_card_type = SupportCardType.SUPPORT_CARD_TYPE_FRIEND
if support_card_favor_process is not SupportCardFavorLevel.SUPPORT_CARD_FAVOR_LEVEL_UNKNOWN:
if (can_incr_aoharu_train) or \
(support_card_favor_process is not SupportCardFavorLevel.SUPPORT_CARD_FAVOR_LEVEL_UNKNOWN):
info = SupportCardInfo(card_type=support_card_type,
favor=support_card_favor_process,
has_event=support_card_event_available)
favor=support_card_favor_process,
can_incr_aoharu_train=can_incr_aoharu_train)
support_card_list_info_result.append(info)
base_y += inc

return support_card_list_info_result
return support_card_list_info_result

# 检测支援卡右上角是否有箭头图标, 同时排除感叹号防止false positive
# 输入的图片必须是彩色的
def detect_aoharu_train_arrow(support_card_icon):
support_card_icon = cv2.cvtColor(support_card_icon, cv2.COLOR_BGR2RGB)
# 定义右上角检测区域
arrow_region_x_start = 110
arrow_region_x_end = 145
arrow_region_y_start = 0
arrow_region_y_end = 40

arrow_region = support_card_icon[arrow_region_y_start:arrow_region_y_end,
arrow_region_x_start:arrow_region_x_end]

# 定义箭头可能的颜色范围 (检查橙色)
orange_lower = [240, 100, 50]
orange_upper = [255, 180, 100]

# 定义红色像素范围(用于检测感叹号)
red_lower = [180, 30,50]
red_upper = [255, 100, 150]

# 计算橙色像素和红色像素的数量
orange_pixels = 0
red_pixels = 0
total_pixels = arrow_region.shape[0] * arrow_region.shape[1]

for y in range(arrow_region.shape[0]):
for x in range(arrow_region.shape[1]):
pixel = arrow_region[y, x]

# 检测橙色像素
if (orange_lower[0] <= pixel[0] <= orange_upper[0] and
orange_lower[1] <= pixel[1] <= orange_upper[1] and
orange_lower[2] <= pixel[2] <= orange_upper[2]):
orange_pixels += 1
# 检测红色像素
elif (red_lower[0] <= pixel[0] <= red_upper[0] and
red_lower[1] <= pixel[1] <= red_upper[1] and
red_lower[2] <= pixel[2] <= red_upper[2]):
red_pixels += 1

orange_ratio = orange_pixels / total_pixels if total_pixels > 0 else 0
red_ratio = red_pixels / total_pixels if total_pixels > 0 else 0

has_arrow = False

# 首先排除感叹号:如果红色像素比例过高,判断为感叹号
if red_ratio > 0.2:
has_arrow = False
# 如果橙色像素比例超过阈值
elif (orange_ratio > 0.05):
has_arrow = True

return has_arrow


# 检测左下角青春杯训练值是否未满
# 如果已满或者不存在UI(比如已经触发了魂爆, 则返回false)
# 否则返回true
def aoharu_train_not_full(support_card_icon) -> bool:
support_card_icon = cv2.cvtColor(support_card_icon, cv2.COLOR_BGR2RGB)
avatar_region_x_start = 5
avatar_region_x_end = 45
avatar_region_y_start = 70
avatar_region_y_end = 110

avatar_region = support_card_icon[avatar_region_y_start:avatar_region_y_end,
avatar_region_x_start:avatar_region_x_end]

total_pixels = avatar_region.shape[0] * avatar_region.shape[1]
if total_pixels == 0:
return False

# 检测灰色
grey_lower = [100, 100, 100]
grey_upper = [150, 150, 150]
grey_pixels = 0

for y in range(avatar_region.shape[0]):
for x in range(avatar_region.shape[1]):
pixel = avatar_region[y, x]
if (grey_lower[0] <= pixel[0] <= grey_upper[0] and
grey_lower[1] <= pixel[1] <= grey_upper[1] and
grey_lower[2] <= pixel[2] <= grey_upper[2]):
grey_pixels += 1

grey_ratio = grey_pixels / total_pixels

if grey_ratio > 0.05:
status = True
else:
status = False

return status
2 changes: 1 addition & 1 deletion module/umamusume/scenario/base_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ def parse_training_result(self, img: any) -> list[int]:
pass

@abstractmethod
def parse_training_support_cord(self, img: any) -> list[SupportCardInfo]:
def parse_training_support_card(self, img: any) -> list[SupportCardInfo]:
"""从屏幕上获取每一张支援卡的信息"""
pass
2 changes: 1 addition & 1 deletion module/umamusume/scenario/ura_scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def parse_training_result(self, img: any) -> list[int]:

return [speed_icr, stamina_incr, power_incr, will_incr, intelligence_incr, skill_point_incr]

def parse_training_support_cord(self, img: any) -> list[SupportCardInfo]:
def parse_training_support_card(self, img: any) -> list[SupportCardInfo]:
base_x = 590
base_y = 190
inc = 120
Expand Down
41 changes: 16 additions & 25 deletions module/umamusume/script/cultivate_task/cultivate.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,6 @@ def script_cultivate_event(ctx: UmamusumeContext):
log.debug("未出现选项")

def script_aoharuhai_race(ctx: UmamusumeContext):
def select_opponent (race_index: int):
match race_index:
case 1:
ctx.ctrl.click(360, 290, "选择第一个对手")
case 2:
ctx.ctrl.click(360, 560, "选择第二个对手")
case 3:
ctx.ctrl.click(360, 830, "选择第三个对手")
time.sleep(2)
ctx.ctrl.click(360, 1080, "开始对战")

img = ctx.ctrl.get_screen(to_gray=True)
if image_match(img, UI_AOHARUHAI_RACE_1).find_match:
race_index = 0
Expand All @@ -260,22 +249,24 @@ def select_opponent (race_index: int):
ctx.ctrl.click(360, 1180, "确认比赛结果")
return

ctx.cultivate_detail.turn_info.aoharu_race_index = race_index
ctx.ctrl.click(360, 1080, "开始青春杯对战")

if race_index == 4:
while True:
time.sleep(1)
img = ctx.ctrl.get_screen(to_gray=True)
if image_match(img, UI_AOHARUHAI_RACE_FINAL_START).find_match:
break
ctx.ctrl.click(360, 980, "确认决赛对手")
else:
while True:
time.sleep(1)
img = ctx.ctrl.get_screen(to_gray=True)
if image_match(img, UI_AOHARUHAI_RACE_SELECT_OPPONENT).find_match:
break
select_opponent(ctx.task.detail.scenario_config.aoharu_config.get_opponent(race_index))
def script_aoharuhai_race_final_start(ctx: UmamusumeContext):
ctx.ctrl.click(360, 980, "确认决赛对手")

def script_aoharuhai_race_select_oponent(ctx: UmamusumeContext):
def select_opponent (race_index: int):
match race_index:
case 1:
ctx.ctrl.click(360, 290, "选择第一个对手")
case 2:
ctx.ctrl.click(360, 560, "选择第二个对手")
case 3:
ctx.ctrl.click(360, 830, "选择第三个对手")
time.sleep(2)
ctx.ctrl.click(360, 1080, "开始对战")
select_opponent(ctx.task.detail.scenario_config.aoharu_config.get_opponent(ctx.cultivate_detail.turn_info.aoharu_race_index))

def script_aoharuhai_race_confirm(ctx: UmamusumeContext):
ctx.ctrl.click(520, 920, "确认对战")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ def aoharuhai_team_name_event(ctx: UmamusumeContext) -> int:
match_result.matched_area[0][0]:match_result.matched_area[1][0]] = 0
else:
break

if ctx.task.detail.scenario_config.aoharu_config.aoharu_team_name_selection == 4:
log.debug("使用选项<胡萝卜>队")
return len(event_selector_list)

event_selector_list.sort(key=lambda x: x.center_point[1])
for i in range(len(event_selector_list)):
event = event_selector_list[i]
Expand Down
2 changes: 1 addition & 1 deletion module/umamusume/script/cultivate_task/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def parse_train_main_menu_operations_availability(ctx: UmamusumeContext, img):


def parse_training_support_card(ctx: UmamusumeContext, img, train_type: TrainingType):
support_card_info_list = ctx.cultivate_detail.scenario.parse_training_support_cord(img)
support_card_info_list = ctx.cultivate_detail.scenario.parse_training_support_card(img)
ctx.cultivate_detail.turn_info.training_info_list[train_type.value - 1].support_card_info_list = support_card_info_list

def parse_train_type(ctx: UmamusumeContext, img) -> TrainingType:
Expand Down
10 changes: 10 additions & 0 deletions module/umamusume/script/cultivate_task/support_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ def get_support_card_score(ctx: UmamusumeContext, info: SupportCardInfo):
score = SCORE_DICT[info.card_type][info.name](ctx, info)
else:
score = SCORE_DICT[info.card_type][DEFAULT](ctx, info)

# 青春杯友情值提高
if info.can_incr_aoharu_train:
date = ctx.cultivate_detail.turn_info.date
if date <= 24:
score += 1
elif date <= 48:
score += 0.5
else:
score += 0.1
return score


Expand Down
Loading