Files
dcalc/backend/api/routes/openapi.py
T
2026-04-08 11:06:30 +08:00

231 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from fastapi.params import Param
from api.core.Gzip import register_gzip_request
import json
from fastapi import APIRouter, Path, Query, Depends
from api.core.Response import response
from api.core.Redis import get_redis_info
from api.dp import RedisDep
import re
from typing import Annotated
from api.types.open import (
JobInfoResponse,
SkillDataSummaryResponse,
SkillDetailResponse,
SkillsListResponse,
SearchSkillResponse,
)
import os
from core.character.adventure import get_adv_list
router = APIRouter()
register_gzip_request(router)
def replace_placeholders(template):
# 匹配 <int>、<float>、<float1>、<float2> 等
pattern = re.compile(r'<(int|float\d*)>')
idx = 0
def repl(match):
nonlocal idx
idx += 1
return f'{{value{idx}}}'
return pattern.sub(repl, template)
@router.get('/skills/', operation_id='skillsList', response_model=SearchSkillResponse)
async def get_skills_list(
redis: RedisDep,
skillName: Annotated[str, Param(..., description='技能名称,支持模糊查询')] = None,
) -> SearchSkillResponse:
"""
根据技能名称,获取对应的技能列表信息
"""
key = 'openapi:skills'
def get_skills():
# This function should retrieve the skills list from the data source
# For now, we return a placeholder list
with open('./openapi/data/skills.json', encoding='utf-8') as f:
skills_data = json.load(f)
return skills_data
skills_list = get_redis_info(redis, key, get_skills)
data = (
list(
filter(
lambda x: re.sub(r'\s+', '', skillName) in re.sub(r'\s+', '', x['skillName']),
skills_list,
)
)
if skillName
else skills_list
)
return response(data=data)
@router.get('/jobInfo/', operation_id='jobsInfo', response_model=JobInfoResponse)
async def get_jobs_info(
redis: RedisDep,
jobName: Annotated[str, Query(..., description='职业名称,支持模糊查询')] = None,
) -> JobInfoResponse:
"""
根据职业名称,获取对应的职业转职信息
"""
adventure_info = get_redis_info(redis, 'dcalc:adventure', get_adv_list)
jobName = jobName.replace('(', '(').replace(')', ')')
result = []
for adv in adventure_info:
matched_children = [child for child in adv.get('children', []) if jobName in child.get('title', '') or jobName in child.get('name', '')]
if matched_children:
parent = {k: v for k, v in adv.items() if k != 'children'}
for child in matched_children:
entry = parent.copy()
entry['child'] = child
result.append(
{
'jobId': entry.get('name', ''),
'jobName': entry.get('title', ''),
'jobGrowId': child.get('name', ''),
'jobGrowName': child.get('title', ''),
}
)
return response(data=result)
@router.get('/{jobId}/{jobGrowId}/skills/', operation_id='skillsByJob', response_model=SkillsListResponse)
async def get_cn_skills_by_job(
redis: RedisDep,
jobId: Annotated[str, Path(..., description='职业')],
jobGrowId: Annotated[str, Path(..., description='转职')],
) -> SkillsListResponse:
"""
获取职业技能列表
"""
key = f'openapi:{jobId}:{jobGrowId}:skills'
def get_skills_by_job():
# This function should retrieve the skills by job and jobGrow
# For now, we return a placeholder list
with open(f'./openapi/data/{jobId}/{jobGrowId}/cn/skill_tree.json', encoding='utf-8') as f:
skills_data = json.load(f)
return skills_data
skills_list = get_redis_info(redis, key, get_skills_by_job)
return response(data=skills_list)
@router.get('/{jobId}/{jobGrowId}/{skillId}/', operation_id='skillDetail', response_model=SkillDetailResponse)
async def get_cn_skill_info(
redis: RedisDep,
jobId: Annotated[str, Path(..., description='职业')],
jobGrowId: Annotated[str, Path(..., description='转职')],
skillId: Annotated[str, Path(..., description='技能')],
level: Annotated[int, Param(..., description='技能等级')] = None,
) -> SkillDetailResponse:
"""
获取技能详细信息
"""
skill_info = {}
key = f'openapi:{jobId}:{jobGrowId}:{skillId}'
try:
def get_skill_info():
# This function should retrieve the skill info based on job and jobGrow
# For now, we return a placeholder dictionary
with open(
f'./openapi/data/{jobId}/{jobGrowId}/cn/skillDetail/{skillId}.json',
encoding='utf-8',
) as f:
skill_data = json.load(f)
if 'levelInfo' in skill_data and 'optionDesc' in skill_data['levelInfo'] and skill_data['levelInfo']['optionDesc'] is not None:
skill_data['levelInfo']['optionDesc'] = replace_placeholders(skill_data['levelInfo']['optionDesc'])
return skill_data
skill_info = get_redis_info(redis, key, get_skill_info)
if level is not None:
level = max(0, min(level, skill_info.get('maxLevel', 0)))
if 'levelInfo' in skill_info and 'rows' in skill_info['levelInfo']:
detail = list(filter(lambda x: x['level'] == level, skill_info['levelInfo']['rows']))
if detail and len(detail) > 0:
skill_info['levelInfo'].update(detail[0])
skill_info['levelInfo']['detail'] = skill_info['levelInfo'].get('optionDesc', '')
for key in skill_info['levelInfo']['optionValue'].keys():
skill_info['levelInfo']['detail'] = skill_info['levelInfo']['detail'].replace(
f'{{{key}}}',
str(skill_info['levelInfo']['optionValue'][key]),
)
del skill_info['levelInfo']['rows']
skill_info['attribute'] = {}
skill_info['attribute'].update(skill_info['levelInfo'])
del skill_info['levelInfo']
except FileNotFoundError:
return response(
code=404,
message=f'技能信息未找到: {jobId} {jobGrowId} {skillId}',
data=None,
)
return response(data=skill_info)
@router.get('/skillData/summary/', operation_id='skillDataSummary', response_model=SkillDataSummaryResponse)
async def get_skill_data_summary(
redis: RedisDep,
job: Annotated[str, Param(..., description='职业')],
skills: Annotated[
str,
Param(
...,
description='技能列表字符串,逗号拼接技能名称,不传递或者传递为空时,查询所有',
),
] = '',
weapons: Annotated[
str,
Param(
...,
description='武器类型列表字符串,逗号拼接武器类型名称,不传递或者传递为空时,查询所有',
),
] = '',
) -> SkillDataSummaryResponse:
"""
获取技能数据汇总信息
"""
job = job.replace('(', '(').replace(')', ')')
key = f'openapi:skillData:summary:{job}'
data = []
skills = skills.split(',') if skills else []
weapons = weapons.split(',') if weapons else []
try:
def get_skill_data_summary():
# This function should retrieve the skill data summary based on job
# For now, we return a placeholder dictionary
summary_dir = './openapi/summary/'
json_files = [f for f in os.listdir(summary_dir) if f.endswith('.json')]
res = []
for i in json_files:
if job in i:
k = re.search(r'^\d+(?:-\d+)?(.*?)_', i)
with open(os.path.join(summary_dir, i), encoding='utf-8') as f:
skill_data = json.load(f)
weapon = i.split('_')[-1].replace('.json', '')
res.append({'weapon': weapon if weapon else '通用', 'skills': skill_data, 'job': k.group(1) if k else ''})
return res
job_summary = get_redis_info(redis, key, get_skill_data_summary)
for item in job_summary:
if len(weapons) == 0 or item['weapon'] in weapons:
items = list(filter(lambda x: x['技能名称'] in skills, item['skills'])) if len(skills) > 0 else item['skills']
for skill in items:
skill['武器类型'] = item['weapon']
skill['职业'] = item['job']
data.extend(items or [])
except FileNotFoundError as e:
print(f'File not found: {e}')
return response(data=[])
return response(data=data)