from copy import deepcopy import re from typing import Any PLACEHOLDER_PATTERN = re.compile(r'<(?:int|float\d*)[^>]*>') VALUE_PATTERN = re.compile(r'\{value\d+\}') def replace_placeholders(template: str) -> str: idx = 0 def repl(_: re.Match[str]) -> str: nonlocal idx idx += 1 return f'{{value{idx}}}' return PLACEHOLDER_PATTERN.sub(repl, template) def normalize_skill_detail(skill_data: dict[str, Any]) -> dict[str, Any]: level_info = skill_data.get('levelInfo') if not isinstance(level_info, dict): return skill_data option_desc = level_info.get('optionDesc') if option_desc is not None: level_info['optionDesc'] = replace_placeholders(option_desc) return skill_data def skill_detail_for_level(skill_data: dict[str, Any], level: int | None) -> dict[str, Any]: result = deepcopy(skill_data) if level is None: return result level = max(0, min(level, result.get('maxLevel', 0))) level_info = result.get('levelInfo') if not isinstance(level_info, dict): return result rows = level_info.get('rows') if not isinstance(rows, list): return result detail = next((row for row in rows if row.get('level') == level), None) if not detail: return result attribute = {**level_info, **detail} attribute['detail'] = attribute.get('optionDesc', '') for key, value in (attribute.get('optionValue') or {}).items(): attribute['detail'] = attribute['detail'].replace(f'{{{key}}}', str(value)) attribute['detail'] = VALUE_PATTERN.sub('-', attribute['detail']) attribute.pop('rows', None) result['attribute'] = attribute result.pop('levelInfo', None) return result