Files
dcalc/backend/api/routes/openapi.py
T
2026-06-02 20:56:07 +08:00

242 lines
8.8 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 api.core.Gzip import register_gzip_request
import json
from fastapi import APIRouter, Path, Query
from api.core.Response import response
from api.core.Redis import get_redis_info
from api.dp import RedisDep
from api.utils.skill_detail import normalize_skill_detail, skill_detail_for_level
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)
@router.get('/skills/', operation_id='skillsList', response_model=SearchSkillResponse)
async def get_skills_list(
redis: RedisDep,
skillName: Annotated[str | None, Query(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:
"""
获取职业技能列表
Args:
jobId (str): 职业ID,必填参数
jobGrowId (str): 转职ID,必填参数
"""
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 | None, Query(description='技能等级')] = None,
) -> SkillDetailResponse:
"""
获取技能详细信息
Args:
jobId (str): 职业ID,必填参数
jobGrowId (str): 转职ID,必填参数
skillId (str): 技能ID,必填参数
level (int, optional): 技能等级,默认为None
"""
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)
return normalize_skill_detail(skill_data)
skill_info = get_redis_info(redis, key, get_skill_info)
skill_info = skill_detail_for_level(skill_info, level)
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, Query(description='职业')],
skills: Annotated[
str,
Query(
description='技能列表字符串,逗号拼接技能名称,不传递或者传递为空时,查询所有',
),
] = '',
weapons: Annotated[
str,
Query(
description='武器类型列表字符串,逗号拼接武器类型名称,不传递或者传递为空时,查询所有',
),
] = '',
) -> SkillDataSummaryResponse:
"""
获取技能数据汇总信息
Args:
job (str): 职业名称,必填参数
skills (str, optional): 技能列表字符串,逗号拼接技能名称,不传递或者传递为空时,查询所有技能,默认为''
weapons (str, optional): 武器类型列表字符串,逗号拼接武器类型名称,不传递或者传递为空时,查询所有武器类型,默认为''
Response:
{
"code": int,
"message": str,
"data": [
{
"技能名称": str,
"武器类型": str,
"职业": str,
"技能描述": str,
"技能等级": int,
"冷却时间": float,
"消耗": str,
"伤害": float,
# 已学等级
"learnedLevel": int | str,
"基础百分比": float | str,
"等效百分比": float | str,
"原始冷却": float | str,
"实际冷却": float | str,
"理论秒伤": float | str,
"SP": float | None | str,
# 所在等级
"unlockAtRoleLevel": str | None,
}
]
}
"""
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)