init
@@ -24,3 +24,9 @@ build
|
||||
resources/
|
||||
**/__ZFJtemp/**
|
||||
web.config
|
||||
|
||||
__pycache__
|
||||
logs
|
||||
AutoRelease
|
||||
*.exe
|
||||
.venv
|
||||
@@ -0,0 +1 @@
|
||||
3.13
|
||||
@@ -0,0 +1,83 @@
|
||||
import base64
|
||||
import hmac
|
||||
import json
|
||||
import time
|
||||
from typing import Optional
|
||||
from core.basic.character import Character
|
||||
from fastapi import Header, Request
|
||||
from api.core.exception import ResponseException
|
||||
|
||||
|
||||
class AlterState:
|
||||
def __init__(self, alter: str, token: str, charcater: Character, equVersion: str):
|
||||
self.alter = alter
|
||||
self.token = token
|
||||
self.origin = alter.split('.')[-1]
|
||||
self.character = charcater
|
||||
self.equVersion = equVersion
|
||||
|
||||
def to_dict(self):
|
||||
return self.__dict__
|
||||
|
||||
|
||||
class Dict(dict):
|
||||
__setattr__ = dict.__setitem__
|
||||
__getattr__ = dict.__getitem__
|
||||
|
||||
|
||||
def dict2obj(dictObj):
|
||||
if not isinstance(dictObj, dict):
|
||||
return dictObj
|
||||
d = Dict()
|
||||
for k, v in dictObj.items():
|
||||
d[k] = dict2obj(v)
|
||||
return d
|
||||
|
||||
|
||||
async def createToken(alter: str, equVersion: str, expire=86400 / 24 * 2, redis=None, env=''):
|
||||
ts_str = str(time.time() + expire)
|
||||
ts_byte = ts_str.encode('utf-8')
|
||||
sha1_tshex_str = hmac.new(alter.encode('utf-8'), ts_byte, 'sha1').hexdigest()
|
||||
token = sha1_tshex_str
|
||||
token = base64.urlsafe_b64encode(token.encode('utf-8')).decode('utf-8')
|
||||
# character = createCharacter(alter)
|
||||
character = {}
|
||||
await redis.set(f'token:{token}', json.dumps(AlterState(alter, token, character, equVersion).to_dict()), int(expire))
|
||||
return token
|
||||
|
||||
|
||||
async def readToken(token: str, redis, env) -> AlterState:
|
||||
info = None
|
||||
try:
|
||||
info = dict2obj(json.loads(await redis.get(f'token:{token}')))
|
||||
except Exception:
|
||||
ResponseException('登录过期或无效Token,请刷新后重试')
|
||||
if info is None:
|
||||
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
||||
return info
|
||||
|
||||
|
||||
def deleteToken(token, redis, env):
|
||||
redis.expire(token, 0)
|
||||
return token
|
||||
|
||||
|
||||
async def authorize(request: Request, access_token: Optional[str] = Header(None)):
|
||||
if access_token is not None:
|
||||
info = await readToken(access_token, request.app.state.redis, request.app.state.env)
|
||||
return info
|
||||
else:
|
||||
raise ResponseException('登录过期或无效Token,请刷新后重试')
|
||||
|
||||
|
||||
def unauthorize(request: Request, access_token: Optional[str] = Header(None)):
|
||||
if access_token is not None:
|
||||
return deleteToken(access_token, request.app.state.redis, request.app.state.env)
|
||||
|
||||
|
||||
async def uid(request: Request, access_uid: Optional[str] = Header(None)):
|
||||
try:
|
||||
return int(access_uid)
|
||||
except Exception:
|
||||
return -1
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import traceback
|
||||
from fastapi import Request, status
|
||||
from fastapi.responses import JSONResponse
|
||||
# from fastapi import Request, status
|
||||
|
||||
from api.core.exception import ResponseException
|
||||
|
||||
logFormatter = logging.Formatter(
|
||||
"""
|
||||
[start]
|
||||
%(asctime)s
|
||||
<%(name)s>
|
||||
%(message)s
|
||||
[end]
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
async def all_exception_handler(request: Request, ex: Exception):
|
||||
# api = str(request.url).split("api/")[1]
|
||||
info = ''
|
||||
if not isinstance(ex, ResponseException):
|
||||
info = traceback.format_exc(limit=-1).strip().split('\n')[1:]
|
||||
info[0] = info[0].split('\\')[-1].replace('"', ':').replace(',', '')
|
||||
info = '\r'.join(info)
|
||||
if request.client.host != '127.0.0.1':
|
||||
from fastapi.logger import logger
|
||||
|
||||
logger.setLevel(logging.ERROR)
|
||||
logger.name = 'dcalc'
|
||||
log_directory = 'logs'
|
||||
import os
|
||||
|
||||
if not os.path.exists('./logs'):
|
||||
os.makedirs('./logs')
|
||||
time_str = datetime.now().strftime('%Y_%m_%d')
|
||||
fileHandler = logging.FileHandler(f'{log_directory}/{logger.name,}_{time_str}.log', encoding='utf-8')
|
||||
fileHandler.setFormatter(logFormatter)
|
||||
fileHandler.setLevel(logging.ERROR)
|
||||
logger.addHandler(fileHandler)
|
||||
try:
|
||||
import pathlib
|
||||
|
||||
pathlib.Path(log_directory).mkdir(parents=True, exist_ok=True)
|
||||
except PermissionError:
|
||||
print('创建日志目录logs失败,请确认是否限制了基础的运行权限')
|
||||
logFunc = logger.error
|
||||
logFunc(info)
|
||||
info = '服务器内部错误'
|
||||
else:
|
||||
info = ex.args[0]
|
||||
# traceback.print_last(sys.exc_info())
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
# 一定要加
|
||||
headers={'Access-Control-Allow-Origin': '*'},
|
||||
content={
|
||||
'code': 500,
|
||||
'message': info,
|
||||
# f"api:{api} \n \r{info}",
|
||||
'data': [],
|
||||
},
|
||||
)
|
||||
@@ -0,0 +1,56 @@
|
||||
import gzip
|
||||
from fastapi import Request, APIRouter, FastAPI
|
||||
from fastapi.responses import Response
|
||||
from typing import Callable
|
||||
from fastapi.middleware.gzip import GZipMiddleware
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
|
||||
class GzipRequest(Request):
|
||||
async def body(self) -> bytes:
|
||||
if not hasattr(self, '_body'):
|
||||
body = await super().body()
|
||||
if 'gzip' in self.headers.getlist('Content-Encoding'):
|
||||
body = gzip.decompress(body)
|
||||
if 'application/json;charset=UTF-8' in self.headers.getlist('Content-Type'):
|
||||
body = body.decode()
|
||||
pass
|
||||
self._body = body
|
||||
return self._body
|
||||
|
||||
|
||||
class GzipRoute(APIRoute):
|
||||
def get_route_handler(self) -> Callable:
|
||||
original_route_handler = super().get_route_handler()
|
||||
|
||||
async def custom_route_handler(request: Request) -> Response:
|
||||
request = GzipRequest(request.scope, request.receive)
|
||||
return await original_route_handler(request)
|
||||
|
||||
return custom_route_handler
|
||||
|
||||
|
||||
def register_gzip_request(router: APIRouter):
|
||||
router.route_class = GzipRoute
|
||||
pass
|
||||
|
||||
|
||||
def register_gzip_response(app: FastAPI):
|
||||
app.add_middleware(GZipMiddleware)
|
||||
pass
|
||||
|
||||
def gzip_zip(content):
|
||||
bytes_com = gzip.compress(str(content).encode('utf-8'))
|
||||
# base64_data = base64.b64encode(bytes_com)
|
||||
# back = base64_data.decode()
|
||||
return bytes_com
|
||||
|
||||
|
||||
def gzip_unzip(content):
|
||||
if content:
|
||||
# base64_data = base64.b64decode(content)
|
||||
bytes_decom = gzip.decompress(content)
|
||||
str_unzip = bytes_decom.decode()
|
||||
return str_unzip
|
||||
else:
|
||||
return None
|
||||
@@ -0,0 +1,21 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
|
||||
def register_cors(app: FastAPI):
|
||||
"""
|
||||
支持跨域
|
||||
:param app:
|
||||
:return:
|
||||
"""
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
# allow_origins = ["http://127.0.0.1:25252"],
|
||||
# allow_origin_regex='https?://(127.0.0.1|localhost|.*.skycity.top|.*.dnftools.com):?.*', # 改成用正则就行了
|
||||
# 改成用正则就行了
|
||||
allow_origin_regex='https?://(127.0.0.1|localhost|.*.dnftools.com|.*.dcalc.cn):?.*',
|
||||
allow_credentials=True,
|
||||
allow_methods=['*'],
|
||||
allow_headers=['*'],
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
import json
|
||||
from api.core.Gzip import gzip_zip, gzip_unzip
|
||||
|
||||
def get_redis_info(redis, key, fun,without_gzip=False):
|
||||
info = None
|
||||
if redis:
|
||||
try:
|
||||
if without_gzip:
|
||||
info = json.loads(redis.get(key))
|
||||
else:
|
||||
info = json.loads(gzip_unzip(redis.get(key)))
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
info = None
|
||||
if info is None:
|
||||
info = fun()
|
||||
if redis and info is not None:
|
||||
if without_gzip:
|
||||
redis.set(key, json.dumps(info))
|
||||
else:
|
||||
redis.set(key, gzip_zip(json.dumps(info)))
|
||||
return info
|
||||
@@ -0,0 +1,41 @@
|
||||
import base64
|
||||
import json
|
||||
from typing import Generic, TypeVar, Union
|
||||
from pydantic.generics import GenericModel
|
||||
import gzip # 导入 gzip 模块
|
||||
from io import BytesIO # 从 io 模块导入 BytesIO 类
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
class Return(GenericModel, Generic[T]):
|
||||
code: int = 200
|
||||
message: str = ''
|
||||
data: Union[T, dict, str] = None
|
||||
|
||||
|
||||
|
||||
# 定义一个函数,将字符串压缩为 gzip 格式,并进行 base64 编码后返回结果
|
||||
def gzip_str(to_gzip: str) -> str:
|
||||
out = BytesIO() # 创建一个 BytesIO 对象
|
||||
with gzip.GzipFile(fileobj=out, mode='w') as f: # 使用 gzip 对象进行数据压缩
|
||||
f.write(to_gzip.encode()) # 将待压缩的字符串写入 gzip 对象中
|
||||
return base64.b64encode(out.getvalue()).decode() # 对压缩后的数据使用 base64 编码并返回结果
|
||||
|
||||
|
||||
def response(*, code=200, data: Union[list, dict, str], message='Success', zip=False):
|
||||
if zip:
|
||||
import gzip
|
||||
data = base64.b64encode(gzip.compress(json.dumps(data).encode()))
|
||||
return Return(code=code, message=message, data=data)
|
||||
|
||||
|
||||
def success(data=None, msg=''):
|
||||
"""成功返回格式"""
|
||||
return response(200, msg, data)
|
||||
|
||||
|
||||
def fail(code=-1, msg='', data=None):
|
||||
"""失败返回格式"""
|
||||
return response(code, msg, data)
|
||||
@@ -0,0 +1,2 @@
|
||||
class ResponseException(Exception):
|
||||
pass
|
||||
@@ -0,0 +1,9 @@
|
||||
from typing import Annotated
|
||||
from redis import Redis
|
||||
from sqlalchemy.orm import Session
|
||||
from fastapi import Depends
|
||||
|
||||
from database.connect import get_db,get_redis
|
||||
|
||||
SessionDep = Annotated[Session, Depends(get_db)]
|
||||
RedisDep = Annotated[Redis, Depends(get_redis)]
|
||||
@@ -0,0 +1,8 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from api.routes import info
|
||||
|
||||
api_router = APIRouter()
|
||||
api_router.include_router(info.router,prefix="/api",tags=["info"])
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
from api.core.Auth import createToken
|
||||
from api.core.Gzip import register_gzip_request
|
||||
import json
|
||||
from fastapi import APIRouter,Request
|
||||
from api.core.Response import Return, response
|
||||
from api.core.Redis import get_redis_info
|
||||
from api.dp import RedisDep
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
register_gzip_request(router)
|
||||
|
||||
|
||||
@router.get('/adventure')
|
||||
async def get_adventure_info(request: Request,redis:RedisDep):
|
||||
def get_adventure():
|
||||
with open('./dataFiles/adventure-info.json', encoding='utf-8') as fp:
|
||||
return json.load(fp)
|
||||
adventure_info = get_redis_info(redis, 'dcalc:adventure', get_adventure)
|
||||
|
||||
return response(data=adventure_info)
|
||||
|
||||
@router.get('/equipment/list')
|
||||
async def get_equipment_list(request: Request,redis:RedisDep):
|
||||
def get_equipment_list():
|
||||
with open('./dataFiles/equipment-list.json', encoding='utf-8') as fp:
|
||||
return json.load(fp)
|
||||
equipment_list = get_redis_info(redis, 'dcalc:equipment', get_equipment_list)
|
||||
|
||||
return response(data=equipment_list)
|
||||
|
||||
@router.get("/token/get/{alter}", response_model=Return[str])
|
||||
async def getToken(
|
||||
alter: str, request: Request, version: str = None, equVersion: str = ""
|
||||
):
|
||||
if version is not None and version != "default" and version != "":
|
||||
alter = version + "." + alter
|
||||
token = createToken(
|
||||
alter, equVersion, redis=request.app.state.redis, env=request.app.state.env
|
||||
)
|
||||
return response(data=token)
|
||||
@@ -0,0 +1,4 @@
|
||||
PORT=17173
|
||||
DEBUG_MODE=True
|
||||
WORKERS=1
|
||||
REDIS_URL=redis://localhost:6379/1
|
||||
@@ -0,0 +1,4 @@
|
||||
PORT=17173
|
||||
DEBUG_MODE=False
|
||||
WORKERS=1
|
||||
REDIS_URL=redis://localhost:6379/1
|
||||
@@ -0,0 +1,14 @@
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
|
||||
class Config(BaseSettings):
|
||||
DEBUG_MODE: bool = True
|
||||
WORKERS: int = 1
|
||||
PORT:int = 17173
|
||||
REDIS_URL: str = 'redis://localhost:56379/1'
|
||||
|
||||
class Config:
|
||||
env_file = ('config/.env', 'config/.env.prod')
|
||||
|
||||
|
||||
config = Config()
|
||||
@@ -0,0 +1,579 @@
|
||||
from functools import cache
|
||||
import importlib
|
||||
from typing import Literal
|
||||
|
||||
from core.basic.property import CharacterInfo
|
||||
from core.basic.skill import Skill
|
||||
|
||||
from core.basic.equipment import get_equipment
|
||||
# from core.basic.equipment import equipments
|
||||
# from core.basic.skill import Skill, ActiveSkill, PassiveSkill
|
||||
from .formula import 获取基础属性
|
||||
from .roleinfo import CharacterEquipInfo, get_key_by_value
|
||||
# from .property import 精通计算, 角色基础, CharacterInfo
|
||||
|
||||
|
||||
class Character:
|
||||
# region 角色属性
|
||||
|
||||
STR: float
|
||||
"""力量"""
|
||||
|
||||
INT: float
|
||||
"""智力"""
|
||||
|
||||
Spirit: float
|
||||
"""精神"""
|
||||
|
||||
Vitality: float
|
||||
"""体力"""
|
||||
|
||||
AtkP: float
|
||||
"""物理攻击力"""
|
||||
|
||||
PAtkP: float
|
||||
"""物理攻击力%"""
|
||||
|
||||
AtkM: float
|
||||
"""魔法攻击力"""
|
||||
PAtkM: float
|
||||
"""魔法攻击力%"""
|
||||
|
||||
AtkI: float
|
||||
"""独立攻击力"""
|
||||
PAtkI: float
|
||||
"""独立攻击力%"""
|
||||
|
||||
ElementA: dict[str, float]
|
||||
"""属性攻击"""
|
||||
|
||||
ElementDB: dict[str, float]
|
||||
"""属性强化数值"""
|
||||
|
||||
ElementR: dict[str, float]
|
||||
"""属性抗性数值"""
|
||||
|
||||
CriticalM: float
|
||||
"""魔法暴击"""
|
||||
|
||||
CriticalP: float
|
||||
"""物理暴击"""
|
||||
|
||||
SkillAttack: float
|
||||
"""技能攻击力"""
|
||||
|
||||
SpeedA: float
|
||||
"""攻击速度"""
|
||||
|
||||
SpeedM: float
|
||||
"""移动速度"""
|
||||
|
||||
SpeedR: float
|
||||
"""施放速度"""
|
||||
|
||||
Hit: float
|
||||
"""命中率"""
|
||||
|
||||
Abnormal: dict[str, bool]
|
||||
"""敌人异常状态"""
|
||||
|
||||
MonsterInfo: dict[str, float]
|
||||
|
||||
Buffer: float
|
||||
"""增益量"""
|
||||
|
||||
BufferP: float
|
||||
"""增益量%"""
|
||||
|
||||
Attack: float
|
||||
"""攻击强化"""
|
||||
|
||||
AttackP: float
|
||||
"""攻击强化%"""
|
||||
|
||||
# endregion
|
||||
|
||||
skills: list["Skill"] = []
|
||||
# """技能列表"""
|
||||
skills_dict: dict[str, "Skill"] = {}
|
||||
# """技能名字对应技能"""
|
||||
equVersion: str = '0'
|
||||
"""装备版本"""
|
||||
charEquipInfo: dict[str, "CharacterEquipInfo"]
|
||||
"""装备打造信息"""
|
||||
|
||||
# region 角色属性
|
||||
输出类型: str = '物理'
|
||||
|
||||
buffer: bool = False
|
||||
# endregion
|
||||
|
||||
# region 职业属性
|
||||
实际名称: str = ''
|
||||
名称: str = ''
|
||||
角色: str = ''
|
||||
角色类型: str = ''
|
||||
职业: str = ''
|
||||
武器选项: list[str] = []
|
||||
输出类型选项: list[str] = []
|
||||
防具精通属性: list[str] = []
|
||||
类型 = ''
|
||||
|
||||
输出类型: str = '物理'
|
||||
|
||||
# endregion
|
||||
|
||||
def __init__(self, equVersion) -> None:
|
||||
self.equVersion = equVersion
|
||||
# self.equs = get_equ(self.equVersion)
|
||||
self.STR = 0
|
||||
self.INT = 0
|
||||
self.AtkP = 0
|
||||
self.AtkM = 0
|
||||
self.AtkI = 0
|
||||
self.PAtkP = 1.0
|
||||
self.PAtkM = 1.0
|
||||
self.PAtkI = 1.0
|
||||
self.ElementA = {
|
||||
'火': False,
|
||||
'冰': False,
|
||||
'光': False,
|
||||
'暗': False,
|
||||
}
|
||||
self.ElementDB = {
|
||||
'火': 0,
|
||||
'冰': 0,
|
||||
'光': 0,
|
||||
'暗': 0,
|
||||
}
|
||||
self.ElementR = {
|
||||
'火': 0,
|
||||
'冰': 0,
|
||||
'光': 0,
|
||||
'暗': 0,
|
||||
}
|
||||
self.Abnormal = {
|
||||
'出血': False,
|
||||
'灼伤': False,
|
||||
'感电': False,
|
||||
'中毒': False,
|
||||
}
|
||||
self.CriticalM = 0
|
||||
self.CriticalP = 0
|
||||
self.SkillAttack = 1
|
||||
self.SpeedA = 0
|
||||
self.SpeedM = 0
|
||||
self.SpeedR = 0
|
||||
self.HitP = 0
|
||||
self.Hit = 0
|
||||
self.MonsterInfo = {
|
||||
'DefenseP': 0,
|
||||
'DefenseM': 0,
|
||||
'火抗': 0,
|
||||
'冰抗': 0,
|
||||
'光抗': 0,
|
||||
'暗抗': 0,
|
||||
}
|
||||
self.Buffer = 0
|
||||
self.BufferP = 1.0
|
||||
self.Attack = 0
|
||||
self.AttackP = 1.0
|
||||
pass
|
||||
|
||||
# region 角色属性设置
|
||||
def SetBaseStatus(self) -> None:
|
||||
"""设角色基础属性"""
|
||||
# 角色四维
|
||||
temp = 获取基础属性(self.角色, self.职业)
|
||||
for index, i in enumerate([get_key_by_value(i) for i in ['力量', '体力', '智力', '精神']]):
|
||||
setattr(self, i, temp[index])
|
||||
# 角色属性抗性
|
||||
pass
|
||||
# 角色异常抗性
|
||||
pass
|
||||
|
||||
def SetStatus(
|
||||
self,
|
||||
力量=0,
|
||||
智力=0,
|
||||
物攻=0,
|
||||
魔攻=0,
|
||||
独立=0,
|
||||
技攻=0,
|
||||
全属强=0,
|
||||
火强=0,
|
||||
冰强=0,
|
||||
光强=0,
|
||||
暗强=0,
|
||||
全属抗=0,
|
||||
火抗=0,
|
||||
冰抗=0,
|
||||
光抗=0,
|
||||
暗抗=0,
|
||||
火属性攻击=False,
|
||||
冰属性攻击=False,
|
||||
光属性攻击=False,
|
||||
暗属性攻击=False,
|
||||
移速=0,
|
||||
攻速=0,
|
||||
施放=0,
|
||||
命中=0,
|
||||
命中率=0,
|
||||
物暴=0,
|
||||
魔暴=0,
|
||||
攻击强化=0,
|
||||
攻击强化P=0,
|
||||
增益量=0,
|
||||
增益量P=0,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""设置角色属性"""
|
||||
allowed_kwargs = {
|
||||
'STR',
|
||||
'INT',
|
||||
'AtkP',
|
||||
'AtkM',
|
||||
'AtkI',
|
||||
'PAtkP',
|
||||
'PAtkM',
|
||||
'PAtkI',
|
||||
'PATKIPDamage',
|
||||
'PDamageC',
|
||||
'PSTR',
|
||||
'PINT',
|
||||
'PDamageB',
|
||||
'ElementA',
|
||||
'ElementDB',
|
||||
'ElementR',
|
||||
'CriticalMP',
|
||||
'CriticalM',
|
||||
'CriticalPP',
|
||||
'CriticalP',
|
||||
'EquipmentSkillAttack',
|
||||
'SkillAttack',
|
||||
'SpeedA',
|
||||
'SpeedM',
|
||||
'SpeedR',
|
||||
'HitP',
|
||||
'Hit',
|
||||
'Attack',
|
||||
'AttackP',
|
||||
'Buffer',
|
||||
'BufferP',
|
||||
}
|
||||
for key in kwargs:
|
||||
if key not in allowed_kwargs:
|
||||
raise ValueError(f'Invalid keyword argument: {key}')
|
||||
self.STR += 力量 + kwargs.get('STR', 0)
|
||||
self.INT += 智力 + kwargs.get('INT', 0)
|
||||
self.AtkP += 物攻 + kwargs.get('AtkP', 0)
|
||||
self.AtkM += 魔攻 + kwargs.get('AtkM', 0)
|
||||
self.AtkI += 独立 + kwargs.get('AtkI', 0)
|
||||
self.PAtkP *= kwargs.get('PAtkP', 0)
|
||||
self.PAtkM *= kwargs.get('PAtkM', 0)
|
||||
self.PAtkI *= kwargs.get('PAtkI', 0)
|
||||
for elem in ['火', '冰', '光', '暗']:
|
||||
self.ElementA[elem] = kwargs.get(f'{elem}属性攻击', False) or kwargs.get('ElementA', {}).get(elem, False) or self.ElementA[elem]
|
||||
self.ElementDB[elem] += kwargs.get(f'{elem}强', 0) + kwargs.get('ElementDB', {}).get(elem, 0) + kwargs.get('全属强', 0)
|
||||
self.ElementR[elem] += kwargs.get(f'{elem}抗', 0) + kwargs.get('ElementR', {}).get(elem, 0) + kwargs.get('全属抗', 0)
|
||||
self.CriticalM += kwargs.get('CriticalM', 0) + 魔暴
|
||||
self.CriticalP += kwargs.get('CriticalP', 0) + 物暴
|
||||
self.SkillAttack += (1 + 技攻) * (1 + kwargs.get('SkillAttack', 0))
|
||||
self.SpeedA += 攻速 + kwargs.get('SpeedA', 0)
|
||||
self.SpeedM += 移速 + kwargs.get('SpeedM', 0)
|
||||
self.SpeedR += 施放 + kwargs.get('SpeedR', 0)
|
||||
self.HitP += 命中率 + kwargs.get('HitP', 0)
|
||||
self.Hit += 命中 + kwargs.get('Hit', 0)
|
||||
self.Attack += 攻击强化 + kwargs.get('Attack', 0)
|
||||
self.AttackP += 攻击强化P + kwargs.get('AttackP', 0)
|
||||
self.Buffer += 增益量 + kwargs.get('Buffer', 0)
|
||||
self.BufferP += 增益量P + kwargs.get('BufferP', 0)
|
||||
pass
|
||||
|
||||
def AddSkillLv(self, min, max, lv, type=-1) -> None:
|
||||
"""
|
||||
增加技能等级
|
||||
type: -1 全部, 0 被动, 1 主动
|
||||
"""
|
||||
for skill in self.skills:
|
||||
if min <= skill.requiredLv <= max:
|
||||
if type == -1 or skill.type == type:
|
||||
skill.AddLv(lv, self)
|
||||
|
||||
def SetSkillCD(self, min=1, max=99, cd=0) -> None:
|
||||
"""
|
||||
设置技能CD
|
||||
type: -1 全部, 0 被动, 1 主动
|
||||
"""
|
||||
for skill in self.skills:
|
||||
if min <= skill.requiredLv <= max and skill.damage:
|
||||
skill.CDR *= 1 - cd
|
||||
|
||||
def GetSkillByName(self, name) -> Skill:
|
||||
"""通过技能名获取技能"""
|
||||
return self.skills_dict.get(name,None)
|
||||
|
||||
def GetSkillByID(self,id:str) -> Skill:
|
||||
skill = list(filter(lambda x:str(x.id) == id,self.skills))
|
||||
"""通过技能ID获取技能"""
|
||||
return skill[0] if len(skill) > 0 else None
|
||||
|
||||
@cache
|
||||
def GetSkillNames(self, type: Literal['active', 'passive', 'all'] = 'all' , damage:Literal[True,False,'all'] = 'all') -> list[str]:
|
||||
"""获取技能名字"""
|
||||
return [skill.name for skill in self.skills if (type == 'all' or skill.type == type) and (damage == 'all' or skill.damage == damage)]
|
||||
|
||||
# endregion
|
||||
|
||||
# region 计算相关
|
||||
def SetDetail(self, info: dict[str, dict]) -> None:
|
||||
self.charEquipInfo = {}
|
||||
"""打造信息导入"""
|
||||
for key in info['equips']:
|
||||
# 导入部位打造信息、装备信息、贴膜信息
|
||||
self.charEquipInfo[key] = CharacterEquipInfo(info['equips'][key], self.equVersion, key)
|
||||
|
||||
# def calc(self):
|
||||
# """计算角色属性"""
|
||||
# func = []
|
||||
# for i in self.charEquipInfo:
|
||||
# # 计算装备
|
||||
# temp = self.equs.get_func_by_id(self.charEquipInfo[i].id)
|
||||
# func.append(temp)
|
||||
# temp(self)
|
||||
# pass
|
||||
|
||||
def getInfo(self):
|
||||
"""返回到前端信息"""
|
||||
info = {}
|
||||
info['alter'] = self.实际名称
|
||||
info['equVersion'] = self.equVersion
|
||||
info['name'] = self.名称
|
||||
info['weaopns'] = self.武器选项
|
||||
skillInfo = []
|
||||
for skill in self.skills:
|
||||
skillInfo.append(
|
||||
{
|
||||
'name': skill.name,
|
||||
'icon': skill.icon,
|
||||
'type': skill.type,
|
||||
# 'SPCost': skill.SPCost,
|
||||
"learnLv": skill.learnLv,
|
||||
"masterLv": skill.masterLv,
|
||||
"maxLv": skill.maxLv,
|
||||
# 'TPCost': 0 if not skill.hasTP else skill.TPCost,
|
||||
# "masterTPLv":0 if not skill.hasTP else skill.masterTPLv,
|
||||
# 'maxTPLv': 0 if not skill.hasTP else skill.TPLearnMax,
|
||||
'positon':skill.position
|
||||
}
|
||||
)
|
||||
info['skills'] = skillInfo
|
||||
equs = []
|
||||
suits = []
|
||||
for i in get_equipment(self.equVersion).equs:
|
||||
equs.append(i.__dict__)
|
||||
for i in get_equipment(self.equVersion).suits:
|
||||
suits.append(i.__dict__)
|
||||
info['equips'] = equs
|
||||
info['suits'] = suits
|
||||
enchats = []
|
||||
emblems = []
|
||||
# 装备过滤
|
||||
# for i in self.equs.info:
|
||||
# if (i.typeSon1Id == '武器' and i.typeSon2Id not in self.武器选项) or (i.name.startswith('精 · ') and self.异界 not in i.name):
|
||||
# pass
|
||||
# else:
|
||||
# equs.append(
|
||||
# {
|
||||
# 'id': i.id,
|
||||
# 'name': i.name,
|
||||
# 'icon': i.icon,
|
||||
# 'typeSon1Id': i.typeSon1Id,
|
||||
# 'typeSon2Id': i.typeSon2Id,
|
||||
# 'typeSon3Id': i.typeSon3Id,
|
||||
# 'rarity': i.rarity,
|
||||
# 'lv': i.lv,
|
||||
# 'suit': i.suit,
|
||||
# }
|
||||
# )
|
||||
# 附魔、徽章
|
||||
# for i in self.equs.prop:
|
||||
# if i.typeSon1Id == '附魔':
|
||||
# enchats.append(
|
||||
# {
|
||||
# 'id': i.id,
|
||||
# 'name': i.name,
|
||||
# 'icon': i.icon,
|
||||
# 'typeSon1Id': i.typeSon1Id,
|
||||
# 'typeSon2Id': i.typeSon2Id,
|
||||
# 'typeSon3Id': i.typeSon3Id,
|
||||
# 'rarity': i.rarity,
|
||||
# 'lv': i.lv,
|
||||
# 'desc': i.desc,
|
||||
# }
|
||||
# )
|
||||
# if i.typeSon1Id == '徽章':
|
||||
# emblems.append(
|
||||
# {
|
||||
# 'id': i.id,
|
||||
# 'name': i.name,
|
||||
# 'icon': i.icon,
|
||||
# 'typeSon1Id': i.typeSon1Id,
|
||||
# 'typeSon2Id': i.typeSon2Id,
|
||||
# 'typeSon3Id': i.typeSon3Id,
|
||||
# 'rarity': i.rarity,
|
||||
# 'lv': i.lv,
|
||||
# 'desc': i.desc,
|
||||
# }
|
||||
# )
|
||||
# info['enchats'] = enchats
|
||||
# info['emblems'] = emblems
|
||||
# info['seal'] = [i.__dict__ for i in self.equs.seal]
|
||||
return info
|
||||
|
||||
def getBasicInos(self):
|
||||
res = []
|
||||
attrs = []
|
||||
if self.输出类型 == '物理':
|
||||
attrs = ['STR', 'PSTR', 'AtkP', 'PAtkP', 'CriticalPP', 'CriticalP']
|
||||
if self.输出类型 == '魔法':
|
||||
attrs = ['INT', 'PINT', 'AtkM', 'PAtkM', 'CriticalMP', 'CriticalM']
|
||||
for attr in attrs + ['PDamage', 'PDamageC', 'PDamageB', 'SpeedA', 'SpeedM', 'SpeedR']:
|
||||
temp = getattr(CharacterInfo, attr)
|
||||
res.append(
|
||||
{
|
||||
'name': temp.name,
|
||||
'value': temp.value(getattr(self, attr)),
|
||||
'icon': temp.icon,
|
||||
}
|
||||
)
|
||||
keys = ['火', '冰', '光', '暗']
|
||||
for index in range(0, 4):
|
||||
temp = getattr(CharacterInfo, f'ElementDB{index}')
|
||||
res.append(
|
||||
{
|
||||
'name': temp.name,
|
||||
'value': temp.value(getattr(self, 'ElementDB')[keys[index]]),
|
||||
'icon': temp.icon,
|
||||
}
|
||||
)
|
||||
temp = getattr(CharacterInfo, f'ElementR{index}')
|
||||
res.append(
|
||||
{
|
||||
'name': temp.name,
|
||||
'value': temp.value(getattr(self, 'ElementR')[keys[index]]),
|
||||
'icon': temp.icon,
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
def calc_init(self, setInfo: dict[str, dict]):
|
||||
# 打造信息导入
|
||||
self.SetDetail(setInfo)
|
||||
# 技能等级设置
|
||||
self.SetSkills(setInfo.get('skills', {}))
|
||||
pass
|
||||
|
||||
def SetSkills(self, skills: dict[str, dict]):
|
||||
"""设置技能等级"""
|
||||
for key in skills:
|
||||
skill = self.GetSkillByID(key)
|
||||
if skill is not None:
|
||||
skill.lv = skills[key].get('lv', 0)
|
||||
pass
|
||||
|
||||
def load_skills(self):
|
||||
pass
|
||||
|
||||
def calc(self, setInfo: dict[str, dict]):
|
||||
funcs = []
|
||||
suits = []
|
||||
self.calc_init(setInfo)
|
||||
# self.SetDetail(setInfo)
|
||||
# 角色基础属性
|
||||
self.SetBaseStatus()
|
||||
return
|
||||
# 技能影响角色的属性,如属强、抗性等
|
||||
for skill in self.skills:
|
||||
skill.effect(self)
|
||||
for i in self.charEquipInfo:
|
||||
# region 装备效果
|
||||
fun = self.equs.get_func_by_id(f'equ_{self.charEquipInfo[i].id}')
|
||||
equ = self.equs.get_equ_by_id(self.charEquipInfo[i].id)
|
||||
if equ is None:
|
||||
continue
|
||||
self.SetStatus(**equ.__dict__)
|
||||
funcs.append(fun + (equ,))
|
||||
# 护甲精通计算
|
||||
if equ.typeSon2Id == self.防具类型:
|
||||
self.SetStatus(**精通计算(equ.lv, equ.rarity, equ.typeSon1Id, equ.typeSon2Id, self.输出类型, self.buffer))
|
||||
# 套装效果
|
||||
suits += (equ.suit or '').split(',')
|
||||
# endregion
|
||||
# region 附魔效果
|
||||
fun = self.equs.get_func_by_id(f'prop_{self.charEquipInfo[i].enchant}')
|
||||
funcs.append(fun + (equ,))
|
||||
# endregion
|
||||
# region 徽章效果
|
||||
for emblem in self.charEquipInfo[i].emblems:
|
||||
fun = self.equs.get_func_by_id(f'prop_{emblem}')
|
||||
funcs.append(fun + (equ,))
|
||||
# endregion
|
||||
# region 魔法封印效果
|
||||
for seal in self.charEquipInfo[i].seals:
|
||||
fun = self.equs.get_func_by_id(f'seal_{seal}')
|
||||
funcs.append(fun + (equ,))
|
||||
# endregion
|
||||
# region 套装效果
|
||||
matchSuit = []
|
||||
for i in list(set(filter(lambda x: x != '' and x is not None, suits))):
|
||||
# 获取当前的套装的数量
|
||||
nums = len(list(filter(lambda x: x == i, suits)))
|
||||
# 获取当前的套装信息
|
||||
suisInfos = list(filter(lambda x: x.suitID == i, self.equs.suit))
|
||||
if len(suisInfos) > 0:
|
||||
matchSuit += [i.id for i in list(filter(lambda x: x.needNum <= nums, suisInfos))]
|
||||
# 兼容于判断
|
||||
if suisInfos[0].compatibility is not None and suisInfos[0].compatibility != '':
|
||||
for compatibility in suisInfos[0].compatibility.split(','):
|
||||
# 兼容于的装备数量
|
||||
numsComp = len(list(filter(lambda x: x == compatibility, suits)))
|
||||
# 大于兼容于小于兼容于加上当前套装数量
|
||||
if numsComp > 0:
|
||||
matchSuit += [
|
||||
i.id
|
||||
for i in list(
|
||||
filter(
|
||||
lambda x: x.suitID == compatibility and numsComp < x.needNum <= nums + numsComp,
|
||||
self.equs.suit,
|
||||
)
|
||||
)
|
||||
]
|
||||
for i in matchSuit:
|
||||
fun = self.equs.get_func_by_id(f'suit_{i}')
|
||||
funcs.append(fun + (None,))
|
||||
# endregion
|
||||
funcs.sort(key=lambda x: x[2])
|
||||
for func in funcs:
|
||||
# 站街
|
||||
func[1](self, func[3], 0)
|
||||
# 进图
|
||||
func[1](self, func[3], 1)
|
||||
return {
|
||||
'basicInfo': self.getBasicInos(),
|
||||
'skillInfo': [],
|
||||
}
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
def createCharacter(alter: str, equVersion: str = '0'):
|
||||
character: Character = None
|
||||
module_name = 'core.characters.' + alter
|
||||
try:
|
||||
character = importlib.import_module(module_name).classChange(equVersion)
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
print('create character ' + module_name + ' error.')
|
||||
pass
|
||||
return character
|
||||
@@ -0,0 +1,125 @@
|
||||
from database.models import Session, EquData, SuitData
|
||||
from database.connect import get_db_engine as get_engine
|
||||
from functools import cache
|
||||
|
||||
|
||||
def parse_to_number_list(info: str, default: list[float] = [0]) -> list[float]:
|
||||
return default if not info else [float(i) for i in info.split(',')]
|
||||
|
||||
|
||||
class Equ:
|
||||
id: str
|
||||
name: str
|
||||
rarity: str
|
||||
itemType: str
|
||||
itemDetailType: str
|
||||
Point: list[float] | float
|
||||
categorize: str
|
||||
imageUrl: str
|
||||
detail: str
|
||||
bufferDetail: str
|
||||
STR: list[float] | float
|
||||
INT: list[float] | float
|
||||
Vitality: list[float] | float
|
||||
Spirit: list[float] | float
|
||||
AtkP: list[float] | float
|
||||
AtkM: list[float] | float
|
||||
AtkI: list[float] | float
|
||||
SkillAttack: list[float] | float
|
||||
Attack: list[float] | float
|
||||
Buffer: list[float] | float
|
||||
max_adaptation: int
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
def adapt(self, adaptation: int = 0):
|
||||
"""调适
|
||||
|
||||
Args:
|
||||
adaptation (int): 调适等级
|
||||
"""
|
||||
temp = self.__dict__.copy()
|
||||
keys = [key for key in EquData.__dict__.keys() if key[0].isupper()]
|
||||
for attr in keys:
|
||||
value = getattr(self, attr)
|
||||
temp[attr] = value[min(adaptation, len(value) - 1)] if isinstance(value, list) else value
|
||||
return Equ(**temp)
|
||||
|
||||
|
||||
class Suit:
|
||||
id: int
|
||||
suitId: int
|
||||
suitName: str
|
||||
rarity: str
|
||||
name: str
|
||||
point: int
|
||||
level: int
|
||||
count: int
|
||||
SkillAttack: float
|
||||
Attack: float
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
|
||||
|
||||
class Equipments:
|
||||
def __init__(self, version='0'):
|
||||
self.version = version
|
||||
self.engine = get_engine(version)
|
||||
self.equs: list[Equ] = []
|
||||
self.equ_dict: dict[str, Equ] = {}
|
||||
self.suits: list[Suit] = []
|
||||
self.suit_dict: dict[str, Suit] = {}
|
||||
self.init_equs()
|
||||
self.init_suits()
|
||||
self.engine.dispose()
|
||||
|
||||
def init_equs(self):
|
||||
"""从数据库中获取所有装备信息"""
|
||||
with Session(self.engine) as session:
|
||||
db_list = session.query(EquData).all()
|
||||
keys = [key for key in EquData.__dict__.keys() if key[0].isupper()] + ['suit']
|
||||
for item in db_list:
|
||||
max_adaptation = 0
|
||||
item.id = str(item.id)
|
||||
for attr in keys:
|
||||
value = parse_to_number_list(getattr(item, attr))
|
||||
max_adaptation = max(max_adaptation, len(value) - 1)
|
||||
setattr(item, attr, value)
|
||||
equ_dict = {k: v for k, v in item.__dict__.items() if not k.startswith('_')}
|
||||
equ_dict['max_adaptation'] = max_adaptation
|
||||
equ = Equ(**equ_dict)
|
||||
self.equs.append(equ)
|
||||
self.equ_dict[equ.id] = equ
|
||||
|
||||
def init_suits(self):
|
||||
"""从数据库中获取所有套装信息"""
|
||||
with Session(self.engine) as session:
|
||||
db_list = session.query(SuitData).all()
|
||||
for item in db_list:
|
||||
suit = Suit(**{k: v for k, v in item.__dict__.items() if not k.startswith('_')})
|
||||
self.suits.append(suit)
|
||||
self.suit_dict.setdefault(str(suit.suitId), []).append(suit)
|
||||
pass
|
||||
|
||||
def get_suit_info(self, suitId: str | int, point: int = 0, count: int = 0) -> list[Suit]:
|
||||
"""根据套装点数返回对应适用的套装属性\n
|
||||
新套装只需要传入suitID和point即可,count默认为0\n
|
||||
老套装需要传入suitID和count即可,point默认为0
|
||||
"""
|
||||
# 先筛选出点数小于等于point和数量小于等于count的套装
|
||||
suits: list[Suit] = [suit for suit in self.suit_dict[str(suitId)] if suit.point <= point and suit.count <= count]
|
||||
result: dict[int, Suit] = {}
|
||||
# 取每种count套装中点数最高的
|
||||
for suit in suits:
|
||||
if suit.count not in result or suit.point > result[suit.count].point:
|
||||
result[suit.count] = suit
|
||||
return list(result.values())
|
||||
|
||||
|
||||
|
||||
@cache
|
||||
def get_equipment(version: str = '0') -> Equipments:
|
||||
# print('加载装备信息')
|
||||
return Equipments(version)
|
||||
@@ -0,0 +1,602 @@
|
||||
# 看看就行, 计算细节通用的数据
|
||||
|
||||
# region
|
||||
def 强化技攻(强化等级, 强化类型, 部位):
|
||||
增幅技攻 = [0] * 11 + [0.2, 0.4, 0.7, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4]
|
||||
强化技攻 = [0] * 13 + [0.4, 0.7, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2]
|
||||
if 强化类型 == '强化':
|
||||
if 部位 not in ['武器', '耳环']:
|
||||
return 0
|
||||
else:
|
||||
return 强化技攻[强化等级]
|
||||
return 增幅技攻[强化等级]
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region 增幅
|
||||
|
||||
|
||||
增幅系数 = (0, 1, 2, 3, 4, 6, 8, 10, 22, 28, 35, 42, 50, 67, 108, 150, 192, 267, 342, 417, 500, 583, 667, 750, 833, 917, 1000, 1083, 1167, 1250, 1333, 1417)
|
||||
增幅成长系数 = {'稀有': 1, '神器': 1.3, '勇者': 1.1, '传说': 1.4, '史诗': 1.5, '神话': 1.6}
|
||||
增幅品级加分 = {'稀有': 45, '神器': 45, '勇者': 45, '传说': 46, '史诗': 46, '神话': 46}
|
||||
# 增幅品级底数 = {'稀有': 5, '神器': 6, '勇者': 5, '传说': 6, '史诗': 7, '神话': 8}
|
||||
# 增幅品级底数_HF = {'稀有': 10, '神器': 11, '勇者': 10, '传说': 11, '史诗': 12, '神话': 13}
|
||||
增幅品级底数 = {'稀有': 10, '神器': 11, '勇者': 10, '传说': 11, '史诗': 12, '神话': 13}
|
||||
|
||||
|
||||
def 增幅计算(装备等级, 品质, 强化等级, 版本='GF'):
|
||||
if 版本 == 'GF':
|
||||
if 品质 == '智慧产物':
|
||||
return 0
|
||||
return int((装备等级 + 增幅品级加分[品质]) * 增幅成长系数[品质] * 增幅系数[强化等级] / 100 - 0.00000001) + 增幅品级底数[品质] + (0 if 强化等级 < 12 else 5)
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region 特殊装备&勋章
|
||||
|
||||
耳环强化系数 = (
|
||||
0,
|
||||
83,
|
||||
124,
|
||||
166,
|
||||
207,
|
||||
248,
|
||||
314,
|
||||
370,
|
||||
426,
|
||||
482,
|
||||
621,
|
||||
970,
|
||||
1455,
|
||||
1941,
|
||||
2911,
|
||||
4043,
|
||||
5175,
|
||||
7116,
|
||||
9056,
|
||||
10997,
|
||||
13099,
|
||||
15363,
|
||||
17627,
|
||||
19891,
|
||||
22155,
|
||||
24420,
|
||||
26684,
|
||||
28948,
|
||||
31212,
|
||||
33476,
|
||||
35740,
|
||||
38004,
|
||||
)
|
||||
左右强化系数 = (
|
||||
0,
|
||||
60,
|
||||
90,
|
||||
120,
|
||||
150,
|
||||
180,
|
||||
210,
|
||||
247,
|
||||
285,
|
||||
322,
|
||||
360,
|
||||
675,
|
||||
1013,
|
||||
1350,
|
||||
2025,
|
||||
2812,
|
||||
3600,
|
||||
4950,
|
||||
6300,
|
||||
7650,
|
||||
9112,
|
||||
10688,
|
||||
12262,
|
||||
13838,
|
||||
15412,
|
||||
16988,
|
||||
18562,
|
||||
20138,
|
||||
21712,
|
||||
23288,
|
||||
24862,
|
||||
26438,
|
||||
)
|
||||
勋章强化系数 = (0, 100, 120, 144, 173, 208, 250, 300, 320, 360, 400, 610, 1220, 2440, 2684, 2952, 3838, 4989, 6486, 8432, 10962)
|
||||
特殊成长系数 = {'普通': 0.4, '高级': 0.7, '稀有': 1, '神器': 1.25, '传说': 1.35, '史诗': 1.45, '神话': 1.55}
|
||||
特殊品级加分 = {'普通': 24, '高级': 30, '稀有': 26, '神器': 28, '传说': 29, '史诗': 30, '神话': 31}
|
||||
|
||||
|
||||
def 耳环计算(装备等级, 品质, 强化等级):
|
||||
if 品质 == '智慧产物':
|
||||
return 0
|
||||
return int((装备等级 + 特殊品级加分[品质]) / 2400 * 特殊成长系数[品质] * 耳环强化系数[强化等级])
|
||||
|
||||
|
||||
def 左右计算(装备等级, 品质, 强化等级):
|
||||
if 品质 == '智慧产物':
|
||||
return 0
|
||||
return int((装备等级 + 特殊品级加分[品质]) / 2400 * 特殊成长系数[品质] * 左右强化系数[强化等级])
|
||||
|
||||
|
||||
def 勋章计算(装备等级, 品质, 强化等级):
|
||||
return int((装备等级 + 特殊品级加分[品质]) / 2400 * 特殊成长系数[品质] * 勋章强化系数[强化等级])
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region 武器
|
||||
|
||||
武器强化系数 = (0, 2, 2.6, 3.6, 4.7, 5.8, 6.9, 8.2, 11, 14.6, 18.7, 26.9, 36.7, 43, 49.2, 55.4, 61.7, 68, 74.3, 80.6, 86.9, 93.2, 99.5, 105.8, 112.1, 118.3, 124.6, 130.9, 137.1, 143.4, 149.7, 156.0)
|
||||
武器锻造系数 = (0, 2, 3, 4, 6, 8, 13, 18, 25, 32, 41)
|
||||
武器成长系数 = {'普通': 0.4, '高级': 0.7, '稀有': 1, '神器': 1.25, '勇者': 1.1, '传说': 1.35, '史诗': 1.45, '神话': 1.55}
|
||||
武器品级加分 = {'普通': 8, '高级': 8, '稀有': 10, '神器': 12, '勇者': 11, '传说': 13, '史诗': 14, '神话': 15}
|
||||
武器类型系数 = {
|
||||
'短剑': (1.095, 1.115),
|
||||
'太刀': (1.095, 1.105),
|
||||
'钝器': (1.11, 1.095),
|
||||
'巨剑': (1.12, 1.09),
|
||||
'光剑': (1.093, 1.09),
|
||||
'手套': (1.095, 1.115),
|
||||
'臂铠': (1.12, 1.09),
|
||||
'爪': (1.1, 1.1),
|
||||
'拳套': (1.105, 1.095),
|
||||
'东方棍': (1.095, 1.1),
|
||||
'左轮枪': (1.087, 1.077),
|
||||
'自动手枪': (1.064, 1.094),
|
||||
'步枪': (1.1, 1.085),
|
||||
'手炮': (1.106, 1.064),
|
||||
'手弩': (1.075, 1.085),
|
||||
'矛': (1.12, 1.085),
|
||||
'棍棒': (1.108, 1.09),
|
||||
'魔杖': (1.09, 1.11),
|
||||
'法杖': (1.095, 1.12),
|
||||
'扫把': (1.1, 1.11),
|
||||
'十字架': (1.1, 1.095),
|
||||
'念珠': (1.09, 1.115),
|
||||
'图腾': (1.105, 1.09),
|
||||
'镰刀': (1.105, 1.105),
|
||||
'战斧': (1.12, 1.085),
|
||||
'匕首': (1.09, 1.089),
|
||||
'双剑': (1.102, 1.08),
|
||||
'手杖': (1.081, 1.115),
|
||||
'苦无': (1.09, 1.11),
|
||||
'长枪': (1.105, 1.09),
|
||||
'战戟': (1.12, 1.085),
|
||||
'光枪': (1.095, 1.115),
|
||||
'暗矛': (1.095, 1.105),
|
||||
'长刀': (1.108, 1.09),
|
||||
'小太刀': (1.1, 1.1),
|
||||
'重剑': (1.12, 1.09),
|
||||
'源力剑': (1.095, 1.115),
|
||||
# todo
|
||||
'神弦弓': (1.1, 1.095),
|
||||
'玄机弓': (1.108, 1.09),
|
||||
'强攻弩': (1.12, 1.09),
|
||||
'妖影弓': (1.095, 1.1),
|
||||
}
|
||||
|
||||
|
||||
def 武器强化计算(装备等级, 品质, 强化等级, 武器类型, 类型):
|
||||
武器系数 = 武器类型系数[武器类型][0 if 类型 == '物理' else 1]
|
||||
return int((装备等级 + 武器品级加分[品质]) / 8 * 武器成长系数[品质] * 武器强化系数[强化等级] * 武器系数)
|
||||
|
||||
|
||||
def 锻造计算(装备等级, 品质, 锻造等级):
|
||||
return round((装备等级 + 武器品级加分[品质]) / 8 * 武器成长系数[品质] * 武器锻造系数[锻造等级])
|
||||
|
||||
|
||||
def 锻造四维(装备等级, 品质, 锻造等级):
|
||||
return round((装备等级 + 武器品级加分[品质]) / 80 * 武器成长系数[品质] * 武器锻造系数[锻造等级])
|
||||
|
||||
|
||||
武器冷却惩罚系数 = {
|
||||
'短剑': (1, 1, 1),
|
||||
'太刀': (0.95, 0.95, 1),
|
||||
'钝器': (1, 1, 1),
|
||||
'巨剑': (1.05, 1, 1),
|
||||
'光剑': (0.9, 1, 1),
|
||||
'手套': (0.9, 1, 1),
|
||||
'臂铠': (1.05, 1, 1),
|
||||
'爪': (1, 1, 1),
|
||||
'拳套': (0.9, 1, 1),
|
||||
'东方棍': (1, 1, 1),
|
||||
'左轮枪': (0.95, 1, 1),
|
||||
'自动手枪': (0.9, 1, 1),
|
||||
'步枪': (1, 1, 1),
|
||||
'手炮': (1.05, 1, 1),
|
||||
'手弩': (0.9, 1, 1),
|
||||
'矛': (1, 0.95, 1),
|
||||
'棍棒': (0.95, 1, 1),
|
||||
'魔杖': (0.95, 1, 1),
|
||||
'法杖': (1, 1.05, 1),
|
||||
'扫把': (1, 1, 1),
|
||||
'十字架': (1, 0.95, 1),
|
||||
'念珠': (0.95, 1, 1),
|
||||
'图腾': (1, 0.95, 1),
|
||||
'镰刀': (0.95, 1, 1),
|
||||
'战斧': (1.05, 0.9, 1),
|
||||
'匕首': (0.9, 0.95, 1),
|
||||
'双剑': (1.05, 0.9, 1),
|
||||
'手杖': (1, 1.05, 1),
|
||||
'苦无': (1, 1, 1),
|
||||
'长枪': (1, 1, 1),
|
||||
'战戟': (1.1, 0.9, 1),
|
||||
'光枪': (1, 1, 1),
|
||||
'暗矛': (0.95, 0.95, 1),
|
||||
'长刀': (1, 1, 1),
|
||||
'小太刀': (0.95, 1, 1),
|
||||
'重剑': (1.05, 1, 1),
|
||||
'源力剑': (1, 1, 1),
|
||||
# todo
|
||||
'神弦弓': (1, 1, 1),
|
||||
'玄机弓': (1, 1, 1),
|
||||
'强攻弩': (1.05, 1, 1),
|
||||
'妖影弓': (0.95, 0.95, 1),
|
||||
}
|
||||
|
||||
MP系数 = {
|
||||
'短剑': (1, 1.15, 1),
|
||||
'太刀': (0.95, 1.05, 1),
|
||||
'钝器': (1.1, 0.95, 1),
|
||||
'巨剑': (1.2, 0.9, 1),
|
||||
'光剑': (0.9, 1, 1),
|
||||
'手套': (0.95, 1.15, 1),
|
||||
'臂铠': (1.2, 0.9, 1),
|
||||
'爪': (1, 1, 1),
|
||||
'拳套': (1.05, 0.95, 1),
|
||||
'东方棍': (0.95, 1, 1),
|
||||
'左轮枪': (1, 0.9, 1),
|
||||
'自动手枪': (0.7, 1.1, 1),
|
||||
'步枪': (1.1, 0.95, 1),
|
||||
'手炮': (1.25, 0.75, 1),
|
||||
'手弩': (0.9, 1, 1),
|
||||
'矛': (1.1, 0.95, 1),
|
||||
'棍棒': (1, 1, 1),
|
||||
'魔杖': (0.95, 1, 1),
|
||||
'法杖': (1, 1.1, 1),
|
||||
'扫把': (1, 1, 1),
|
||||
'十字架': (1, 0.95, 1),
|
||||
'念珠': (0.9, 1.15, 1),
|
||||
'图腾': (1.05, 0.9, 1),
|
||||
'镰刀': (0.95, 1, 1),
|
||||
'战斧': (1.2, 0.85, 1),
|
||||
'匕首': (1, 0.9, 1),
|
||||
'双剑': (1.2, 0.8, 1),
|
||||
'手杖': (0.95, 1.15, 1),
|
||||
'苦无': (1, 1.1, 1),
|
||||
'长枪': (1.1, 1, 1),
|
||||
'战戟': (1.2, 0.9, 1),
|
||||
'光枪': (1, 1.15, 1),
|
||||
'暗矛': (0.95, 1.05, 1),
|
||||
'长刀': (1.1, 1, 1),
|
||||
'小太刀': (1, 1, 1),
|
||||
'重剑': (1.2, 0.9, 1),
|
||||
'源力剑': (1, 1.15, 1),
|
||||
# todo
|
||||
'神弦弓': (1, 1, 1),
|
||||
'玄机弓': (1.1, 1, 1),
|
||||
'强攻弩': (1.2, 0.9, 1),
|
||||
'妖影弓': (0.95, 1, 1),
|
||||
}
|
||||
|
||||
|
||||
def 武器冷却惩罚(武器类型, 输出类型):
|
||||
类型系数 = 0 if 输出类型 == '物理百分比' else (1 if 输出类型 == '魔法百分比' else 2)
|
||||
return 武器冷却惩罚系数[武器类型][类型系数]
|
||||
# else:
|
||||
# return 武器冷却惩罚系数_HF[武器类型][类型系数]
|
||||
|
||||
|
||||
def 武器MP系数(武器类型, 输出类型, 版本='GF') -> float:
|
||||
类型系数 = 0 if 输出类型 == '物理百分比' else (1 if 输出类型 == '魔法百分比' else 2)
|
||||
if 版本 == 'GF':
|
||||
return MP系数[武器类型][类型系数]
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region 防具
|
||||
|
||||
# 部位系数 = {'上衣': 0.30, '头肩': 0.20, '下装': 0.25, '腰带': 0.10, '鞋': 0.15}
|
||||
# 品级加分 = {'稀有': 5, '神器': 8, '勇者': 11, '传说': 14, '史诗': 17, '智慧产物': 17, '神话': 18}
|
||||
|
||||
|
||||
# def 精通计算(装备等级, 品质, 强化等级, 部位):
|
||||
# return round((20 + 2.5 * (装备等级 + 品级加分[品质] + int(强化等级 / 3))) * 部位系数[部位], 2)
|
||||
|
||||
# def 辅助精通计算(装备等级, 品质, 强化等级, 部位):
|
||||
# return round((4 + (装备等级 + 品级加分[品质] + int(强化等级 / 3))) * 部位系数[部位], 2)
|
||||
|
||||
甲类系数 = {'皮甲': 2.9, '板甲': 2.9, '重甲': 3.1, '轻甲': 3.2, '布甲': 3.2}
|
||||
部位系数 = {'上衣': 0.30, '头肩': 0.20, '下装': 0.25, '腰带': 0.10, '鞋': 0.15}
|
||||
品级加分 = {'稀有': 5, '神器': 8, '勇者': 11, '传说': 14, '史诗': 17, '智慧产物': 17, '神话': 18}
|
||||
|
||||
|
||||
def 精通计算(装备等级, 品质, 强化等级, 部位, 甲类):
|
||||
return round((20 + 甲类系数[甲类] * (装备等级 + 品级加分[品质] + int(强化等级 / 3))) * 部位系数[部位], 2)
|
||||
|
||||
|
||||
def 辅助精通计算(装备等级, 品质, 强化等级, 部位, 属性):
|
||||
if 属性 == '智力':
|
||||
return round((8 + 2.4 * (装备等级 + 品级加分[品质] + int(强化等级 / 3))) * 部位系数[部位], 2)
|
||||
if 属性 == '体力':
|
||||
return round((4 + 1.6 * (装备等级 + 品级加分[品质] + int(强化等级 / 3))) * 部位系数[部位], 2)
|
||||
if 属性 == '精神':
|
||||
return round((8 + 0.8 * (装备等级 + 品级加分[品质] + int(强化等级 / 3))) * 部位系数[部位], 2)
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
# region 角色基础属性
|
||||
|
||||
当前等级 = 110
|
||||
|
||||
# 力量 体力 智力 精神
|
||||
角色基础系数 = {
|
||||
'魔枪士': (4.6, 4.6, 4.4, 4.4, 7, 7, 5, 5),
|
||||
'格斗家(女)': (5, 5, 4, 4, 7.5, 7.5, 4.5, 4.5),
|
||||
'格斗家(男)': (5, 5, 4, 4, 7.5, 7.5, 4.5, 4.5),
|
||||
'枪剑士': (4.6, 4.6, 4.4, 4.4, 7, 7, 5, 5),
|
||||
'神枪手(女)': (4.5, 4.5, 4.5, 4.5, 6.5, 6.5, 5.5, 5.5),
|
||||
'神枪手(男)': (4.5, 4.5, 4.5, 4.5, 6.5, 6.5, 5.5, 5.5),
|
||||
'守护者': (4.8, 4.8, 4.2, 4.2, 7, 7, 5, 5),
|
||||
'魔法师(女)': (4, 4, 5, 5, 4.5, 4.5, 7.5, 7.5),
|
||||
'魔法师(男)': (3.5, 4, 5.5, 5, 4, 4.5, 8, 7.5),
|
||||
'暗夜使者': (5, 4, 5, 4, 7.5, 5.5, 6.5, 4.5),
|
||||
'缔造者': (4, 4, 5, 5, 4.5, 4.5, 7.5, 7.5),
|
||||
'黑暗武士': (4.8, 4.8, 4.2, 4.2, 7.5, 7.5, 4.5, 4.5),
|
||||
'鬼剑士(男)': (4.8, 4.8, 4.2, 4.2, 7.5, 7.5, 4.5, 4.5),
|
||||
'鬼剑士(女)': (4.6, 4.6, 4.4, 4.4, 7, 7, 5, 5),
|
||||
'圣职者(男)': (4.7, 4.8, 4, 4.5, 6.5, 6.5, 4.5, 6.5),
|
||||
'圣职者(女)': (4.7, 4.8, 4, 4.5, 6.5, 6.5, 4.5, 6.5),
|
||||
# todo
|
||||
'弓箭手': (4.6, 4.6, 4.4, 4.4, 7, 7, 5, 5),
|
||||
}
|
||||
|
||||
# 力量 体力 智力 精神
|
||||
职业基础数据 = {
|
||||
'征战者-魔枪士': (5.5, 5.5, 3.5, 3.5),
|
||||
'决战者-魔枪士': (5, 5, 4, 4),
|
||||
'狩猎者-魔枪士': (3, 4.5, 6, 4.5),
|
||||
'暗枪士-魔枪士': (3.5, 3.5, 5.5, 5.5),
|
||||
'气功师-格斗家(女)': (3.5, 3.5, 5.5, 5.5),
|
||||
'散打-格斗家(女)': (5.5, 5.5, 3.5, 3.5),
|
||||
'街霸-格斗家(女)': (5, 4, 5, 4),
|
||||
'柔道家-格斗家(女)': (5, 6, 3.5, 3.5),
|
||||
'气功师-格斗家(男)': (3.5, 3.5, 5.5, 5.5),
|
||||
'散打-格斗家(男)': (5.5, 5.5, 3.5, 3.5),
|
||||
'街霸-格斗家(男)': (5, 4, 5, 4),
|
||||
'柔道家-格斗家(男)': (5, 6, 3.5, 3.5),
|
||||
'暗刃-枪剑士': (5.5, 5.5, 3.5, 3.5),
|
||||
'特工-枪剑士': (5, 5, 4, 4),
|
||||
'战线佣兵-枪剑士': (5.2, 5, 3.5, 4.3),
|
||||
'源能专家-枪剑士': (3.5, 3.5, 5.5, 5.5),
|
||||
'漫游枪手-神枪手(女)': (5.5, 5.5, 3.5, 3.5),
|
||||
'枪炮师-神枪手(女)': (5.5, 5.5, 3.5, 3.5),
|
||||
'机械师-神枪手(女)': (3.5, 3.5, 5.5, 5.5),
|
||||
'弹药专家-神枪手(女)': (4.7, 4.3, 4.7, 4.3),
|
||||
'漫游枪手-神枪手(男)': (5.5, 5.5, 3.5, 3.5),
|
||||
'枪炮师-神枪手(男)': (5.5, 5.5, 3.5, 3.5),
|
||||
'机械师-神枪手(男)': (3.5, 3.5, 5.5, 5.5),
|
||||
'弹药专家-神枪手(男)': (4.7, 4.3, 4.7, 4.3),
|
||||
'合金战士-神枪手(男)': (5.5, 5.5, 3.5, 3.5),
|
||||
'精灵骑士-守护者': (5, 5, 4, 4),
|
||||
'混沌魔灵-守护者': (3.5, 3.5, 5.5, 5.5),
|
||||
'帕拉丁-守护者': (5, 5.5, 2, 5.5),
|
||||
'龙骑士-守护者': (5, 5, 4, 4),
|
||||
'元素师-魔法师(女)': (3.5, 3.5, 5.5, 5.5),
|
||||
'召唤师-魔法师(女)': (3.8, 3.7, 5.3, 5.2),
|
||||
'战斗法师-魔法师(女)': (5, 4, 5, 4),
|
||||
'魔道学者-魔法师(女)': (4.5, 4, 5.2, 4.3),
|
||||
'小魔女-魔法师(女)': (4.7, 4.8, 5.5, 4.5),
|
||||
'元素爆破师-魔法师(男)': (3.5, 3.5, 5.5, 5.5),
|
||||
'冰结师-魔法师(男)': (3.5, 3.7, 5.5, 5.2),
|
||||
'血法师-魔法师(男)': (5.5, 5.5, 3.5, 3.5),
|
||||
'逐风者-魔法师(男)': (5.5, 5.2, 3.5, 3.8),
|
||||
'次元行者-魔法师(男)': (3.5, 3.5, 5.5, 5.5),
|
||||
'刺客-暗夜使者': (5.3, 4.5, 4.2, 4),
|
||||
'死灵术士-暗夜使者': (4.7, 3.5, 5.3, 4.5),
|
||||
'忍者-暗夜使者': (4.5, 3.5, 5.5, 4.5),
|
||||
'影舞者-暗夜使者': (5.5, 4.5, 4, 4),
|
||||
'缔造者-魔法师(女)': (4, 4, 5, 5),
|
||||
'黑暗武士-鬼剑士(男)': (4.8, 4.8, 4.2, 4.2),
|
||||
'剑魂-鬼剑士(男)': (5, 5, 4, 4),
|
||||
'鬼泣-鬼剑士(男)': (3.5, 3.5, 5.5, 5.5),
|
||||
'狂战士-鬼剑士(男)': (5.5, 5.5, 3.5, 3.5),
|
||||
'阿修罗-鬼剑士(男)': (3, 4.5, 6, 4.5),
|
||||
'剑影-鬼剑士(男)': (5, 5, 4, 4),
|
||||
'刃影-鬼剑士(女)': (5, 5, 4, 4),
|
||||
'驭剑士-鬼剑士(女)': (5, 5, 4, 4),
|
||||
'暗殿骑士-鬼剑士(女)': (3.5, 3.5, 5.5, 5.5),
|
||||
'契魔者-鬼剑士(女)': (5.5, 5.5, 3.5, 3.5),
|
||||
'流浪武士-鬼剑士(女)': (5.5, 5.5, 3.5, 3.5),
|
||||
'圣骑士-圣职者(男)': (3.5, 5.5, 3.5, 5.5),
|
||||
'蓝拳圣使-圣职者(男)': (5.2, 5, 3.9, 3.9),
|
||||
'驱魔师-圣职者(男)': (5, 4, 5, 4),
|
||||
'复仇者-圣职者(男)': (3.5, 3.5, 5.5, 5.5),
|
||||
'圣骑士-圣职者(女)': (3.5, 5.5, 5.5, 3.5),
|
||||
'异端审判者-圣职者(女)': (5.2, 5, 3.5, 4.3),
|
||||
'巫女-圣职者(女)': (3.5, 3.5, 5.5, 5.5),
|
||||
'诱魔者-圣职者(女)': (3.5, 3.5, 5.5, 5.5),
|
||||
# todo
|
||||
'缪斯-弓箭手': (3.5, 5.5, 3.5, 5.5),
|
||||
'旅人-弓箭手': (5.5, 5.5, 3.5, 3.5),
|
||||
'猎人-弓箭手': (5.5, 5.5, 3.5, 3.5),
|
||||
'妖护使-弓箭手': (5.5, 5.5, 3.5, 3.5),
|
||||
}
|
||||
|
||||
# 火抗 冰抗 光抗 暗抗
|
||||
|
||||
职业属性抗性数据 = {
|
||||
'征战者-魔枪士': (23, 23, 23, 23),
|
||||
'决战者-魔枪士': (23, 23, 23, 23),
|
||||
'狩猎者-魔枪士': (23, 23, 23, 23),
|
||||
'暗枪士-魔枪士': (23, 23, 23, 23),
|
||||
'气功师-格斗家(女)': (23, 23, 93, -7),
|
||||
'散打-格斗家(女)': (23, 23, 43, 3),
|
||||
'街霸-格斗家(女)': (23, 23, 43, 3),
|
||||
'柔道家-格斗家(女)': (23, 23, 43, 3),
|
||||
'气功师-格斗家(男)': (23, 23, 63, -7),
|
||||
'散打-格斗家(男)': (23, 23, 43, 3),
|
||||
'街霸-格斗家(男)': (23, 23, 43, 3),
|
||||
'柔道家-格斗家(男)': (23, 23, 43, 3),
|
||||
'暗刃-枪剑士': (23, 23, 23, 23),
|
||||
'特工-枪剑士': (23, 23, 23, 23),
|
||||
'战线佣兵-枪剑士': (23, 23, 23, 23),
|
||||
'源能专家-枪剑士': (23, 23, 23, 23),
|
||||
'漫游枪手-神枪手(女)': (23, 23, 23, 23),
|
||||
'枪炮师-神枪手(女)': (23, 23, 23, 23),
|
||||
'机械师-神枪手(女)': (23, 23, 23, 23),
|
||||
'弹药专家-神枪手(女)': (23, 23, 23, 23),
|
||||
'漫游枪手-神枪手(男)': (23, 23, 23, 23),
|
||||
'枪炮师-神枪手(男)': (23, 23, 23, 23),
|
||||
'机械师-神枪手(男)': (23, 23, 23, 23),
|
||||
'弹药专家-神枪手(男)': (23, 23, 23, 23),
|
||||
'合金战士-神枪手(男)': (23, 23, 23, 23),
|
||||
'精灵骑士-守护者': (28, 28, 28, 28),
|
||||
'混沌魔灵-守护者': (28, 28, 28, 28),
|
||||
'帕拉丁-守护者': (28, 28, 28, 28),
|
||||
'龙骑士-守护者': (28, 28, 28, 28),
|
||||
'元素师-魔法师(女)': (23, 23, 23, 23),
|
||||
'召唤师-魔法师(女)': (23, 23, 23, 23),
|
||||
'战斗法师-魔法师(女)': (23, 23, 23, 23),
|
||||
'魔道学者-魔法师(女)': (23, 23, 23, 23),
|
||||
'小魔女-魔法师(女)': (23, 23, 23, 23),
|
||||
'元素爆破师-魔法师(男)': (23, 23, 23, 23),
|
||||
'冰结师-魔法师(男)': (23, 23, 23, 23),
|
||||
'血法师-魔法师(男)': (23, 23, 23, 23),
|
||||
'逐风者-魔法师(男)': (23, 23, 23, 23),
|
||||
'次元行者-魔法师(男)': (23, 23, 23, 23),
|
||||
'刺客-暗夜使者': (23, 23, 23, 23),
|
||||
'死灵术士-暗夜使者': (23, 23, 3, 43),
|
||||
'忍者-暗夜使者': (31, 23, 23, 23),
|
||||
'影舞者-暗夜使者': (23, 23, 23, 23),
|
||||
'缔造者-魔法师(女)': (23, 23, 23, 23),
|
||||
'黑暗武士-鬼剑士(男)': (23, 23, 3, 43),
|
||||
'剑魂-鬼剑士(男)': (23, 23, 3, 43),
|
||||
'鬼泣-鬼剑士(男)': (23, 23, -7, 63),
|
||||
'狂战士-鬼剑士(男)': (23, 23, 3, 43),
|
||||
'阿修罗-鬼剑士(男)': (23, 23, 3, 43),
|
||||
'剑影-鬼剑士(男)': (23, 23, 3, 43),
|
||||
'刃影-鬼剑士(女)': (23, 23, 3, 43),
|
||||
'驭剑士-鬼剑士(女)': (23, 23, 3, 43),
|
||||
'暗殿骑士-鬼剑士(女)': (23, 23, 3, 43),
|
||||
'契魔者-鬼剑士(女)': (23, 23, 3, 43),
|
||||
'流浪武士-鬼剑士(女)': (23, 23, 3, 43),
|
||||
'圣骑士-圣职者(男)': (23, 23, 23, 23),
|
||||
'蓝拳圣使-圣职者(男)': (23, 23, 23, 23),
|
||||
'驱魔师-圣职者(男)': (23, 23, 23, 23),
|
||||
'复仇者-圣职者(男)': (23, 23, 23, 23),
|
||||
'圣骑士-圣职者(女)': (23, 23, 43, 23),
|
||||
'异端审判者-圣职者(女)': (23, 23, 23, 23),
|
||||
'巫女-圣职者(女)': (23, 23, 23, 23),
|
||||
'诱魔者-圣职者(女)': (23, 23, 23, 23),
|
||||
# todo
|
||||
'缪斯-弓箭手': (23, 23, 23, 23),
|
||||
'旅人-弓箭手': (23, 23, 23, 23),
|
||||
'猎人-弓箭手': (23, 23, 23, 23),
|
||||
'妖护使-弓箭手': (23, 23, 23, 23),
|
||||
}
|
||||
|
||||
# 出血 中毒 灼伤 感电 冰冻 减速 眩晕 诅咒 失明 石化 睡眠 混乱 束缚
|
||||
职业异常抗性数据 = {
|
||||
'征战者-魔枪士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'决战者-魔枪士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'狩猎者-魔枪士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'暗枪士-魔枪士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'气功师-格斗家(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0.05, 0, 0, 0, 0),
|
||||
'散打-格斗家(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'街霸-格斗家(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'柔道家-格斗家(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'气功师-格斗家(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0.05, 0, 0, 0, 0),
|
||||
'散打-格斗家(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'街霸-格斗家(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'柔道家-格斗家(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'暗刃-枪剑士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'特工-枪剑士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'战线佣兵-枪剑士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'源能专家-枪剑士': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'漫游枪手-神枪手(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'枪炮师-神枪手(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'机械师-神枪手(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'弹药专家-神枪手(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'漫游枪手-神枪手(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'枪炮师-神枪手(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'机械师-神枪手(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'弹药专家-神枪手(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'合金战士-神枪手(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'精灵骑士-守护者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'混沌魔灵-守护者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'帕拉丁-守护者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'龙骑士-守护者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'元素师-魔法师(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'召唤师-魔法师(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'战斗法师-魔法师(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'魔道学者-魔法师(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'小魔女-魔法师(女)': (0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0),
|
||||
'元素爆破师-魔法师(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'冰结师-魔法师(男)': (0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'血法师-魔法师(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'逐风者-魔法师(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'次元行者-魔法师(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'刺客-暗夜使者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'死灵术士-暗夜使者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'忍者-暗夜使者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'影舞者-暗夜使者': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'缔造者-魔法师(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'黑暗武士-鬼剑士(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'剑魂-鬼剑士(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'鬼泣-鬼剑士(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'狂战士-鬼剑士(男)': (0, 0, 0, 0, 0, 0, 0.95, 0, 0, 0, 0.95, 0, 0),
|
||||
'阿修罗-鬼剑士(男)': (0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0),
|
||||
'剑影-鬼剑士(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'刃影-鬼剑士(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'驭剑士-鬼剑士(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'暗殿骑士-鬼剑士(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'契魔者-鬼剑士(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'流浪武士-鬼剑士(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'圣骑士-圣职者(男)': (0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0, 0.05),
|
||||
'蓝拳圣使-圣职者(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'驱魔师-圣职者(男)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'复仇者-圣职者(男)': (0, 0, 0, 0, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3),
|
||||
'圣骑士-圣职者(女)': (0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05),
|
||||
'异端审判者-圣职者(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'巫女-圣职者(女)': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'诱魔者-圣职者(女)': (0, 0, 0, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5),
|
||||
# todo
|
||||
'缪斯-弓箭手': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'旅人-弓箭手': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'猎人-弓箭手': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
'妖护使-弓箭手': (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
}
|
||||
|
||||
|
||||
def 获取基础属性(角色, 职业):
|
||||
角色数据 = 角色基础系数[角色]
|
||||
职业数据 = 职业基础数据[职业 + '-' + 角色]
|
||||
|
||||
唤醒 = 335 if 当前等级 >= 75 else (145 if 当前等级 >= 15 else 0)
|
||||
|
||||
力量 = int(角色数据[4] + 角色数据[0] * min(14, 当前等级 - 1) + 职业数据[0] * max(当前等级 - 15, 0) + 唤醒 + 93 + 当前等级)
|
||||
体力 = int(角色数据[5] + 角色数据[1] * min(14, 当前等级 - 1) + 职业数据[1] * max(当前等级 - 15, 0) + 唤醒 + 93 + 当前等级)
|
||||
智力 = int(角色数据[6] + 角色数据[2] * min(14, 当前等级 - 1) + 职业数据[2] * max(当前等级 - 15, 0) + 唤醒 + 93 + 当前等级)
|
||||
精神 = int(角色数据[7] + 角色数据[3] * min(14, 当前等级 - 1) + 职业数据[3] * max(当前等级 - 15, 0) + 唤醒 + 93 + 当前等级)
|
||||
return (力量, 智力, 体力, 精神)
|
||||
|
||||
|
||||
def 获取属性抗性基础(角色, 职业):
|
||||
return 职业属性抗性数据[职业 + '-' + 角色]
|
||||
|
||||
|
||||
def 获取异常抗性基础(角色, 职业):
|
||||
return 职业异常抗性数据[职业 + '-' + 角色]
|
||||
|
||||
|
||||
刀魂之卡赞 = (0, 31, 40, 48, 58, 67, 79, 90, 103, 116, 131, 145, 161, 178, 194, 212, 230, 250, 270, 292, 313)
|
||||
|
||||
部位列表 = ('上衣', '头肩', '下装', '腰带', '鞋', '手镯', '项链', '戒指', '耳环', '辅助装备', '魔法石', '武器')
|
||||
|
||||
# endregion
|
||||
@@ -0,0 +1,77 @@
|
||||
import enum
|
||||
|
||||
|
||||
class CharacterInfo(enum.Enum):
|
||||
def __init__(self, name, icon, func) -> None:
|
||||
self._name = name
|
||||
self._icon = icon
|
||||
self._func = func
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
return self._icon
|
||||
|
||||
def value(self, value):
|
||||
return self._func(value)
|
||||
|
||||
STR = '力量', '/ui/UI_ProfileIcon_002.png', lambda x: round(x, 0)
|
||||
"""力量"""
|
||||
|
||||
INT = '智力', '/ui/UI_ProfileIcon_003.png', lambda x: round(x, 0)
|
||||
"""智力"""
|
||||
|
||||
AtkP = '物理攻击力', '/ui/UI_ProfileIcon_006.png', lambda x: round(x, 0)
|
||||
"""物理攻击力"""
|
||||
|
||||
AtkM = '魔法攻击力', '/ui/UI_ProfileIcon_007.png', lambda x: round(x, 0)
|
||||
"""魔法攻击力"""
|
||||
|
||||
AtkI = '独立攻击力', '/ui/UI_ProfileIcon_008.png', lambda x: round(x, 0)
|
||||
"""独立攻击力"""
|
||||
|
||||
ElementA: dict[str, float]
|
||||
# """属性攻击"""
|
||||
|
||||
ElementDB0 = '火属性强化', '/ui/UI_ProfileIcon_022.png', lambda x: round(x, 0)
|
||||
|
||||
ElementR0 = '火属性抗性', '/ui/UI_ProfileIcon_023.png', lambda x: round(x, 0)
|
||||
|
||||
ElementDB1 = '冰属性强化', '/ui/UI_ProfileIcon_024.png', lambda x: round(x, 0)
|
||||
|
||||
ElementR1 = '冰属性抗性', '/ui/UI_ProfileIcon_025.png', lambda x: round(x, 0)
|
||||
|
||||
ElementDB2 = '光属性强化', '/ui/UI_ProfileIcon_026.png', lambda x: round(x, 0)
|
||||
|
||||
ElementR2 = '光属性抗性', '/ui/UI_ProfileIcon_027.png', lambda x: round(x, 0)
|
||||
|
||||
ElementDB3 = '暗属性强化', '/ui/UI_ProfileIcon_028.png', lambda x: round(x, 0)
|
||||
|
||||
ElementR3 = '暗属性抗性', '/ui/UI_ProfileIcon_029.png', lambda x: round(x, 0)
|
||||
|
||||
CriticalP = '物理暴击', '/ui/UI_ProfileIcon_011.png', lambda x: f'{format(x * 100, ".2f")}%'
|
||||
"""物理暴击"""
|
||||
|
||||
CriticalM = '魔法暴击', '/ui/UI_ProfileIcon_010.png', lambda x: f'{format(x * 100, ".2f")}%'
|
||||
"""魔法暴击"""
|
||||
|
||||
EquipmentSkillAttack = '技能攻击力增加', '/ui/UI_ProfileIcon_047.png', lambda x: f'{format(x * 100 - 100, ".2f")}%'
|
||||
"""技能攻击力"""
|
||||
|
||||
SpeedA = '攻击速度', '/ui/UI_ProfileIcon_012.png', lambda x: f'{format(x * 100, ".2f")}%'
|
||||
"""攻击速度"""
|
||||
|
||||
SpeedM = '移动速度', '/ui/UI_ProfileIcon_014.png', lambda x: f'{format(x * 100, ".2f")}%'
|
||||
"""移动速度"""
|
||||
|
||||
SpeedR = '施放速度', '/ui/UI_ProfileIcon_013.png', lambda x: f'{format(x * 100, ".2f")}%'
|
||||
"""施放速度"""
|
||||
|
||||
# HitP : float
|
||||
# """命中率"""
|
||||
|
||||
# Hit : float
|
||||
# """命中"""
|
||||
@@ -0,0 +1,96 @@
|
||||
from enum import Enum
|
||||
from typing import Union
|
||||
|
||||
from core.basic.equipment import Equ, get_equipment
|
||||
|
||||
|
||||
class CharacterEquipInfo:
|
||||
id: str
|
||||
"""装备ID"""
|
||||
reinforce: int
|
||||
"""强化等级"""
|
||||
reinforceType: int
|
||||
"""强化类型"""
|
||||
enchant: str
|
||||
"""附魔"""
|
||||
emblems: list[str]
|
||||
"""徽章"""
|
||||
fusion: int | None
|
||||
"""贴膜ID"""
|
||||
refine: int | None
|
||||
"""锻造等级"""
|
||||
fusionDetail: dict | None
|
||||
"""贴膜详情"""
|
||||
adaptation: int
|
||||
"""调适等级"""
|
||||
equInfo: Union['Equ', None]
|
||||
"""装备信息"""
|
||||
fusionInfo: Union['Equ', None]
|
||||
"""贴膜信息"""
|
||||
|
||||
def __init__(self, info={}, equVerison=0, part='') -> None:
|
||||
self.__dict__.update(info)
|
||||
equ = get_equipment(equVerison).equ_dict.get(self.id, None)
|
||||
if equ is not None and (equ.itemType == part or equ.itemDetailType == part):
|
||||
self.equInfo = equ.adapt(self.adaptation)
|
||||
else:
|
||||
self.equInfo = None
|
||||
|
||||
|
||||
class CharacterWeaponInfo(CharacterEquipInfo):
|
||||
refine: int
|
||||
"""锻造等级"""
|
||||
upgradeDetail: dict
|
||||
"""贴膜详情"""
|
||||
|
||||
def __init__(self, info={}) -> None:
|
||||
self.__dict__.update(info)
|
||||
|
||||
|
||||
class Part(Enum):
|
||||
weaopn = '武器'
|
||||
title = '称号'
|
||||
coat = '上衣'
|
||||
neck = '护肩'
|
||||
pants = '下装'
|
||||
shoes = '鞋子'
|
||||
belt = '腰带'
|
||||
bracelet = '手镯'
|
||||
ring = '戒指'
|
||||
necklace = '项链'
|
||||
support = '辅助装备'
|
||||
magic_stone = '魔法石'
|
||||
earring = '耳环'
|
||||
|
||||
|
||||
class CharacterAttributes(Enum):
|
||||
STR = '力量'
|
||||
INT = '智力'
|
||||
Spirit = '精神'
|
||||
Vitality = '体力'
|
||||
AtkP = '物理攻击力'
|
||||
AtkM = '魔法攻击力'
|
||||
AtkI = '独立攻击力'
|
||||
ElementA = '属性攻击'
|
||||
ElementDB = '属性强化数值'
|
||||
ElementR = '属性抗性数值'
|
||||
CriticalM = '魔法暴击'
|
||||
CriticalP = '物理暴击'
|
||||
SkillAttack = '技能攻击力'
|
||||
SpeedA = '攻击速度'
|
||||
SpeedM = '移动速度'
|
||||
SpeedR = '施放速度'
|
||||
Hit = '命中率'
|
||||
Abnormal = '敌人异常状态'
|
||||
MonsterInfo = '怪物信息'
|
||||
Buffer = '增益量'
|
||||
BufferP = '增益量%'
|
||||
Attack = '攻击强化'
|
||||
AttackP = '攻击强化%'
|
||||
|
||||
|
||||
mapping = {value: key for key, value in CharacterAttributes.__members__.items()}
|
||||
|
||||
|
||||
def get_key_by_value(value: str) -> str:
|
||||
return mapping[value]
|
||||
@@ -0,0 +1,178 @@
|
||||
from copy import deepcopy
|
||||
import re
|
||||
from typing import Literal, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.basic.character import Character
|
||||
|
||||
characterLv = 120 + 5
|
||||
|
||||
|
||||
class Skill:
|
||||
name: str = ''
|
||||
"""技能名称"""
|
||||
_lv: int = 0
|
||||
id: int = 0
|
||||
"""技能ID"""
|
||||
icon: str = '$char/$name'
|
||||
"""技能图标,默认当前职业下该技能名称对应的图标,支持以下模板字符串
|
||||
$common 通用图标路径
|
||||
$char 当前职业图标路径
|
||||
$name 技能名称
|
||||
$id 技能ID
|
||||
"""
|
||||
type: Literal['active', 'passive'] = 'active'
|
||||
"""技能类型 active主动 passive被动"""
|
||||
learnLv: int = 0
|
||||
"""学习等级"""
|
||||
masterLv: int = 0
|
||||
"""精通等级"""
|
||||
maxLv: int = 0
|
||||
"""最大等级"""
|
||||
position: int = 0
|
||||
"""技能树位置"""
|
||||
rangeLv: int = 1
|
||||
"""学习间隔"""
|
||||
cube: int = 0
|
||||
"""无色消耗"""
|
||||
skillRation: int = 1
|
||||
"""技能面板倍率 [改变技能面板]"""
|
||||
skillDamage: int = 1
|
||||
"""技能技攻 [不改变技能面板]"""
|
||||
char: 'Character' = None
|
||||
"""技能所属角色"""
|
||||
damage: bool = False
|
||||
"""是否是伤害技能"""
|
||||
cd: float = 0
|
||||
"""技能冷却时间"""
|
||||
cdReduce: float = 1
|
||||
"""技能冷却缩减"""
|
||||
cdRecover: float = 1
|
||||
"""技能冷却恢复"""
|
||||
associate: list = []
|
||||
"""关联技能
|
||||
type: 关联类型 *乘算 +加算 $角色属性 默认'*skillRation'
|
||||
e.g.
|
||||
*skillRation 乘算技能面板倍率
|
||||
*cdReduce 乘算技能冷却缩减
|
||||
$*PATK 乘算角色物理攻击
|
||||
~直接走type对应的函数名称 传参为old,new,data,skills
|
||||
skills: 关联技能 默认 '*'
|
||||
"""
|
||||
|
||||
def __init__(self, char):
|
||||
self.char = char
|
||||
self.id = self._extract_id()
|
||||
self.icon = self._generate_icon()
|
||||
# self.lv = self._calculate_lv()
|
||||
pass
|
||||
|
||||
def _extract_id(self):
|
||||
className = self.__class__.__name__
|
||||
return int(re.search(r'\d+', className).group()) if re.search(r'\d+', className) else 0
|
||||
|
||||
def _generate_icon(self):
|
||||
icon = self.icon or '$char/$name'
|
||||
icon = icon.replace('$char', f'/characters/{self.char.name}/skill')
|
||||
icon = icon.replace('$common', '/characters/common')
|
||||
icon = icon.replace('$name', f'{self.name}')
|
||||
icon = icon.replace('$id', f'{self.id}')
|
||||
return icon
|
||||
|
||||
def _calculate_lv(self):
|
||||
return min(int((characterLv - self.learnLv) / self.rangeLv + 1), self.masterLv) if self._lv == 0 else self._lv
|
||||
|
||||
@property
|
||||
def lv(self):
|
||||
"""技能等级"""
|
||||
return self._lv
|
||||
|
||||
@lv.setter
|
||||
def lv(self, value):
|
||||
value = min(self.maxLv, value)
|
||||
if self._lv != value:
|
||||
self.effect(self._lv, value)
|
||||
self._lv = value
|
||||
|
||||
def effect(self, old: int, new: int):
|
||||
for assoc in self.associate:
|
||||
type = assoc.get('type', '*skillRation')
|
||||
skills = assoc.get('skills', 'all')
|
||||
data = assoc.get('data', [0] * self.maxLv)
|
||||
if type[0] not in ['*', '+', '$']:
|
||||
if self.precondition():
|
||||
getattr(self, type)(old, new, data, skills)
|
||||
continue
|
||||
if self.precondition():
|
||||
self._apply_association(type, old, new, data, skills)
|
||||
|
||||
def precondition(self):
|
||||
"""effect的前置条件"""
|
||||
return True
|
||||
|
||||
def _apply_association(self, type, old, new, data, skills):
|
||||
if type.startswith('$*'):
|
||||
value = (1 + data[new] / 100) / (1 + data[old] / 100)
|
||||
eval(f'self.char.SetStatus({type[2:]}={value})')
|
||||
elif type.startswith('$+'):
|
||||
value = data[new] / 100 - data[old] / 100
|
||||
eval(f'self.char.SetStatus({type[2:]}={value})')
|
||||
else:
|
||||
if skills == '*':
|
||||
skills = self.char.GetSkillNames('all', True)
|
||||
for name in skills:
|
||||
skill = self.char.GetSkillByName(name)
|
||||
if skill is not None:
|
||||
self._update_skill_attribute(skill,type, old, new, data)
|
||||
|
||||
def _update_skill_attribute(self,skill, type, old, new, data):
|
||||
if type.startswith('*'):
|
||||
setattr(skill, type[1:], getattr(skill, type[1:]) * (1 + data[new] / 100) / (1 + data[old] / 100))
|
||||
elif type.startswith('+'):
|
||||
setattr(skill, type[1:], getattr(skill, type[1:]) + data[new] / 100 - data[old] / 100)
|
||||
|
||||
|
||||
|
||||
class ActiveSkill(Skill):
|
||||
type: str = 'active'
|
||||
"""技能类型 active主动 passive被动"""
|
||||
damage: bool = True
|
||||
"""是否是伤害技能"""
|
||||
|
||||
def __init__(self, char):
|
||||
super().__init__(char)
|
||||
|
||||
def skillInfo(self, mode: str | None = None):
|
||||
basic = self
|
||||
if mode is not None:
|
||||
basic = deepcopy(self)
|
||||
basic.setMode(mode)
|
||||
else:
|
||||
basic = self
|
||||
date = basic.getSkillDate(self.lv)
|
||||
cd = basic.getSkillCD()
|
||||
return date * self.skillRation , self.skillDamage ,cd
|
||||
|
||||
def setMode(self, mode: str):
|
||||
pass
|
||||
|
||||
def getSkillDate(self,lv:int=0):
|
||||
res = 0
|
||||
for i in range(0,10):
|
||||
data = getattr(self, f'data{i}', [])
|
||||
if len(data) == 0:
|
||||
break
|
||||
if lv < len(data):
|
||||
hit = getattr(self, f'hit{i}', 1)
|
||||
power = getattr(self, f'power{i}', 1)
|
||||
res += hit * power * data[lv]
|
||||
return res
|
||||
|
||||
def getSkillCD(self):
|
||||
return self.cd * self.cdReduce / self.cdRecover
|
||||
|
||||
class PassiveSkill(Skill):
|
||||
type: str = 'passive'
|
||||
"""技能类型 active主动 passive被动"""
|
||||
damage: bool = False
|
||||
"""是否是伤害技能"""
|
||||
@@ -0,0 +1,154 @@
|
||||
# 944b9aab492c15a8474f96947ceeb9e4
|
||||
from core.basic.skill import PassiveSkill, ActiveSkill, characterLv
|
||||
from core.basic.character import Character
|
||||
|
||||
|
||||
class Skill0(ActiveSkill):
|
||||
# 기본기 숙련
|
||||
# https://api.neople.co.kr/df/skills/944b9aab492c15a8474f96947ceeb9e4/5a56514f35cf0270ae8d6c65f8fefd78?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
name = '基础精通'
|
||||
icon = '$common/$name'
|
||||
learnLv = 1
|
||||
masterLv = characterLv
|
||||
maxLv = 200
|
||||
position = 0
|
||||
rangeLv = 1
|
||||
damage = False
|
||||
type = 'passive'
|
||||
|
||||
|
||||
data0 = [0, 150, 158.7, 167.3, 176, 184.5, 193.2, 201.8, 210.5, 219.2, 227.7, 236.4, 245, 253.7, 262.2, 270.9, 284.3, 297.6, 311, 324.3, 337.7, 350.9, 364.2, 377.6, 390.9, 404.3, 417.6, 431, 444.3, 457.7, 471, 484.2, 497.6, 510.9, 524.3, 537.6, 551, 564.3, 577.7, 591, 604.4, 617.7, 630.9, 644.3, 657.6, 671, 684.3, 697.7, 711, 724.4, 737.7, 751.1, 764.3, 777.6, 791, 804.3, 817.7, 831, 844.4, 857.7, 871.1, 884.4, 897.8, 911, 924.3, 937.7, 951, 964.4, 977.7, 991.1, 1004.4, 1017.8, 1031.1, 1044.5, 1057.7, 1071, 1084.4, 1097.7, 1111.1, 1124.4, 1137.8, 1151.1, 1164.5, 1177.8, 1191, 1204.4, 1217.7, 1231.1, 1244.4, 1257.8, 1271.1, 1284.5, 1297.8, 1311.2, 1324.5, 1337.7, 1351.1, 1364.4, 1377.8, 1391.1, 1404.5, 1417.8, 1431.2, 1444.5, 1457.9, 1471.2, 1484.6, 1497.9, 1511.3, 1524.6, 1538, 1551.3, 1564.7, 1578, 1591.4, 1604.7, 1618.1, 1631.4, 1644.8, 1658.1, 1671.5, 1684.8, 1698.2, 1711.5, 1724.9, 1738.2, 1751.6, 1764.9, 1778.3, 1791.6, 1805, 1818.3, 1831.7, 1845, 1858.4, 1871.7, 1885.1, 1898.4, 1911.8, 1925.1, 1938.5, 1951.8, 1965.2, 1978.5, 1991.9, 2005.2, 2018.6, 2031.9, 2045.3, 2058.6, 2072, 2085.3, 2098.7, 2112, 2125.4, 2138.7, 2152.1, 2165.4, 2178.8, 2192.1, 2205.5, 2218.8, 2232.2, 2245.5, 2258.9, 2272.2, 2285.6, 2298.9, 2312.3, 2325.6, 2339, 2352.3, 2365.7, 2379, 2392.4, 2405.7, 2419.1, 2432.4, 2445.8, 2459.1, 2472.5, 2485.8, 2499.2, 2512.5, 2525.9, 2539.2, 2552.6, 2565.9, 2579.3, 2592.6, 2606, 2619.3, 2632.7, 2646, 2659.4, 2672.7, 2686.1, 2699.4, 2712.8, 2726.1, 2739.5]# noqa: E501
|
||||
|
||||
# G-14手雷 G-14 파열류탄
|
||||
# https://api.neople.co.kr/df/skills/944b9aab492c15a8474f96947ceeb9e4/de3fea2d65c597f4d55c70a02b97fc79?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
class Skill1(ActiveSkill):
|
||||
name = "G-14手雷"
|
||||
learnLv = 15
|
||||
masterLv = 60
|
||||
maxLv = 70
|
||||
position = 5
|
||||
rangeLv = 2
|
||||
cd = 2
|
||||
mp = [20, 160]
|
||||
|
||||
data0 = [0, 751, 830, 904, 981, 1057, 1132, 1210, 1287, 1362, 1438, 1516, 1591, 1668, 1746, 1819, 1897, 1972, 2049, 2127, 2202, 2278, 2355, 2429, 2508, 2584, 2659, 2735, 2814, 2888, 2965, 3041, 3116, 3194, 3271, 3346, 3422, 3500, 3575, 3652, 3732, 3806, 3883, 3961, 4034, 4112, 4189, 4264, 4342, 4418, 4493, 4570, 4648, 4723, 4799, 4876, 4950, 5029, 5105, 5180, 5256, 5335, 5409, 5486, 5562, 5637, 5715, 5792, 5867, 5943, 6021]# noqa: E501
|
||||
|
||||
class Skill2(PassiveSkill):
|
||||
# 니트로 모터
|
||||
# https://api.neople.co.kr/df/skills/944b9aab492c15a8474f96947ceeb9e4/4224f9b0b8c7c903e9a1e0f9d9f6d04d?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
name = '单兵推进器'
|
||||
learnLv = 15
|
||||
masterLv = 10
|
||||
maxLv = 20
|
||||
position = 8
|
||||
rangeLv = 1
|
||||
|
||||
data0 = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40]
|
||||
data1 = [0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
|
||||
|
||||
associate = [
|
||||
{'data': data0, 'skills': ['交叉射击', '聚合弹', '凝固汽油弹', '超真空弹:切利']},
|
||||
{'data': data1, 'skills': ['爆裂弹']}
|
||||
]
|
||||
|
||||
|
||||
class Skill3(PassiveSkill):
|
||||
# 병기 숙련
|
||||
# https://api.neople.co.kr/df/skills/944b9aab492c15a8474f96947ceeb9e4/bae12a6dc7d22a5cf149673e88ddda28?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
name = '兵器研究'
|
||||
learnLv = 20
|
||||
masterLv = 10
|
||||
maxLv = 20
|
||||
position = 0
|
||||
rangeLv = 3
|
||||
|
||||
data0 = [0, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48] # noqa: E501
|
||||
associate = [{'data': data0, 'type': '$*PAtkI'}]
|
||||
|
||||
# def precondition(self):
|
||||
# weapon = self.char.charEquipInfo['武器'].equInfo
|
||||
# if weapon is not None and (weapon.itemDetailType == '手弩' or weapon.itemDetailType == '步枪' or weapon.categorize == '传世武器'):
|
||||
# return True
|
||||
# return False
|
||||
|
||||
class Skill4(PassiveSkill):
|
||||
# 강화탄
|
||||
# https://api.neople.co.kr/df/skills/944b9aab492c15a8474f96947ceeb9e4/3829c15bf5f520c13998a3479ba0ce7b?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
name = '弹药改良'
|
||||
learnLv = 20
|
||||
masterLv = 10 # todo
|
||||
maxLv = 20
|
||||
position = 1 # todo
|
||||
rangeLv = 3
|
||||
|
||||
data0 = [0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10] # noqa: E501
|
||||
data1 = [0, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33] # noqa: E501
|
||||
|
||||
|
||||
class Skill5(PassiveSkill):
|
||||
# 유탄 마스터리
|
||||
# https://api.neople.co.kr/df/skills/944b9aab492c15a8474f96947ceeb9e4/0113c8b1306ca76d208f83f2d093dd62?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
name = '手雷精通'
|
||||
learnLv = 20
|
||||
masterLv = 10
|
||||
maxLv = 20
|
||||
position = 7
|
||||
rangeLv = 3
|
||||
|
||||
data0 = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200] # noqa: E501
|
||||
|
||||
associate = [{'type': '*skillRation', 'data': data0, 'skills': ['G-14手雷']}]
|
||||
|
||||
class Skill6(ActiveSkill):
|
||||
# M18 클레이모어
|
||||
# https://api.neople.co.kr/df/skills/944b9aab492c15a8474f96947ceeb9e4/2ff50c35efcf0f287c4c418c8454da48?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
name = "M18阔剑地雷"
|
||||
learnLv = 20
|
||||
masterLv = 60 #todo
|
||||
maxLv = 70
|
||||
position = 8 #todo
|
||||
rangeLv = 2
|
||||
cd = 6
|
||||
mp = [70, 588]
|
||||
|
||||
data0 = [0, 2094, 2307, 2519, 2732, 2944, 3157, 3368, 3580, 3793, 4009, 4221, 4434, 4646, 4859, 5071, 5284, 5496, 5709, 5921, 6132, 6344, 6557, 6769, 6982, 7198, 7410, 7623, 7835, 8048, 8260, 8473, 8685, 8896, 9109, 9321, 9534, 9746, 9959, 10171, 10384, 10600, 10812, 11025, 11237, 11450, 11660, 11873, 12085, 12298, 12510, 12723, 12935, 13148, 13360, 13573, 13789, 14001, 14212, 14425, 14637, 14850, 15062, 15275, 15487, 15700, 15912, 16125, 16337, 16550, 16762]# noqa: E501
|
||||
|
||||
class classChange(Character):
|
||||
def __init__(self, equVersion=''):
|
||||
|
||||
super().__init__(equVersion)
|
||||
self.name = 'spitfire_female'
|
||||
self.nameShow = '重霄·弹药专家'
|
||||
self.role = 'gunner_female'
|
||||
|
||||
# 用来筛CP武器的
|
||||
# self.转职 = '弹药专家(女)'
|
||||
self.武器选项 = ['手弩', '步枪']
|
||||
self.输出类型选项 = ['魔法固伤', '物理固伤']
|
||||
self.防具精通属性 = ['智力', '力量']
|
||||
self.类型 = '魔法固伤'
|
||||
self.武器类型 = '手弩'
|
||||
self.防具类型 = '皮甲'
|
||||
self.buff = 1.84
|
||||
|
||||
self.load_skills()
|
||||
|
||||
def load_skills(self):
|
||||
"""加载技能"""
|
||||
skills = []
|
||||
skills_dict = {}
|
||||
i = 0
|
||||
while i >= 0:
|
||||
try:
|
||||
tem = eval('Skill' + str(i) + '(char=self)')
|
||||
skills_dict[tem.name] = tem
|
||||
skills.append(tem)
|
||||
i += 1
|
||||
except Exception as e:
|
||||
print(e)
|
||||
i = -1
|
||||
self.skills = skills
|
||||
self.skills_dict = skills_dict
|
||||
|
||||
def set_skill_info(self, info, rune_except=[], clothes_pants=[]):
|
||||
super().set_skill_info(info, rune_except=['爆裂弹'], clothes_pants=['远古记忆'])
|
||||
@@ -0,0 +1,35 @@
|
||||
#41f1cdc2ff58bb5fdc287be0db2a8df3
|
||||
from core.basic.skill import PassiveSkill, ActiveSkill, characterLv
|
||||
from core.basic.character import Character
|
||||
|
||||
# 基础精通 기본기 숙련
|
||||
# https://api.neople.co.kr/df/skills/41f1cdc2ff58bb5fdc287be0db2a8df3/5a56514f35cf0270ae8d6c65f8fefd78?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
class Skill0(ActiveSkill):
|
||||
name = '基础精通'
|
||||
icon = '$common$name'
|
||||
learnLv = 1
|
||||
masterLv = characterLv
|
||||
maxLv = 200
|
||||
position = 0
|
||||
rangeLv = 1
|
||||
damage = False
|
||||
type = 'passive'
|
||||
|
||||
data0 = [0, 150, 158.7, 167.3, 176, 184.5, 193.2, 201.8, 210.5, 219.2, 227.7, 236.4, 245, 253.7, 262.2, 270.9, 284.3, 297.6, 311, 324.3, 337.7, 350.9, 364.2, 377.6, 390.9, 404.3, 417.6, 431, 444.3, 457.7, 471, 484.2, 497.6, 510.9, 524.3, 537.6, 551, 564.3, 577.7, 591, 604.4, 617.7, 630.9, 644.3, 657.6, 671, 684.3, 697.7, 711, 724.4, 737.7, 751.1, 764.3, 777.6, 791, 804.3, 817.7, 831, 844.4, 857.7, 871.1, 884.4, 897.8, 911, 924.3, 937.7, 951, 964.4, 977.7, 991.1, 1004.4, 1017.8, 1031.1, 1044.5, 1057.7, 1071, 1084.4, 1097.7, 1111.1, 1124.4, 1137.8, 1151.1, 1164.5, 1177.8, 1191, 1204.4, 1217.7, 1231.1, 1244.4, 1257.8, 1271.1, 1284.5, 1297.8, 1311.2, 1324.5, 1337.7, 1351.1, 1364.4, 1377.8, 1391.1, 1404.5, 1417.8, 1431.2, 1444.5, 1457.9, 1471.2, 1484.6, 1497.9, 1511.3, 1524.6, 1538, 1551.3, 1564.7, 1578, 1591.4, 1604.7, 1618.1, 1631.4, 1644.8, 1658.1, 1671.5, 1684.8, 1698.2, 1711.5, 1724.9, 1738.2, 1751.6, 1764.9, 1778.3, 1791.6, 1805, 1818.3, 1831.7, 1845, 1858.4, 1871.7, 1885.1, 1898.4, 1911.8, 1925.1, 1938.5, 1951.8, 1965.2, 1978.5, 1991.9, 2005.2, 2018.6, 2031.9, 2045.3, 2058.6, 2072, 2085.3, 2098.7, 2112, 2125.4, 2138.7, 2152.1, 2165.4, 2178.8, 2192.1, 2205.5, 2218.8, 2232.2, 2245.5, 2258.9, 2272.2, 2285.6, 2298.9, 2312.3, 2325.6, 2339, 2352.3, 2365.7, 2379, 2392.4, 2405.7, 2419.1, 2432.4, 2445.8, 2459.1, 2472.5, 2485.8, 2499.2, 2512.5, 2525.9, 2539.2, 2552.6, 2565.9, 2579.3, 2592.6, 2606, 2619.3, 2632.7, 2646, 2659.4, 2672.7, 2686.1, 2699.4, 2712.8, 2726.1, 2739.5]# noqa: E501
|
||||
|
||||
# 空中连斩 공중 연속 베기
|
||||
# https://api.neople.co.kr/df/skills/41f1cdc2ff58bb5fdc287be0db2a8df3/78bd107acd474518b606be1e4fd38239?apikey=fdvit1Kj64EAJm0qfB3JEAD8FLExLDD0
|
||||
class Skill2(ActiveSkill):
|
||||
name = "空中连斩"
|
||||
learnLv = 5
|
||||
masterLv = 1
|
||||
maxLv = 11
|
||||
position = 0 #todo
|
||||
rangeLv = 1
|
||||
mp = [5, 7]
|
||||
|
||||
data0 = [0, 195, 209, 221, 234, 247, 260, 275, 286, 299, 312, 326]# noqa: E501
|
||||
data1 = [0, 144, 154, 163, 173, 182, 192, 202, 211, 221, 230, 240]# noqa: E501
|
||||
|
||||
def effect(self, old , new):
|
||||
pass
|
||||
@@ -0,0 +1,38 @@
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
|
||||
host_window = r'C:\Windows\System32\drivers\etc\hosts'
|
||||
host_mac = r'/etc/hosts'
|
||||
|
||||
|
||||
HOST_LIVE = ['#dcalc', '127.0.0.1:17173 www.dcalc.com']
|
||||
|
||||
|
||||
def search_host(hostvalue):
|
||||
if platform.system().lower() != 'windows':
|
||||
host_path = host_mac
|
||||
else:
|
||||
host_path = host_window
|
||||
hostfile = open(host_path, 'r', errors='ignore')
|
||||
each_line = hostfile.readlines()
|
||||
hostfile.close()
|
||||
findresult = re.findall(hostvalue, ''.join(each_line))
|
||||
return findresult
|
||||
|
||||
|
||||
def write_host(hostvalue):
|
||||
if platform.system().lower() != 'windows':
|
||||
output = open(host_mac, 'a')
|
||||
else:
|
||||
output = open(host_window, 'a')
|
||||
|
||||
for insid in hostvalue:
|
||||
output.write(insid)
|
||||
output.write('\n')
|
||||
output.close()
|
||||
|
||||
|
||||
def host_init():
|
||||
if not search_host(HOST_LIVE[0]):
|
||||
write_host(HOST_LIVE)
|
||||
@@ -0,0 +1,30 @@
|
||||
# 用于实现排行的最小堆
|
||||
from heapq import heapify, heappush, heappushpop
|
||||
|
||||
|
||||
class MinHeap:
|
||||
def __init__(self, top_n, h=[]):
|
||||
self.h = h[:]
|
||||
self.length = top_n
|
||||
heapify(self.h)
|
||||
|
||||
def add(self, element):
|
||||
if len(self.h) < self.length:
|
||||
heappush(self.h, element)
|
||||
else:
|
||||
heappushpop(self.h, element)
|
||||
|
||||
def getTop(self):
|
||||
return sorted(self.h, reverse=True)
|
||||
|
||||
def merge(self, other):
|
||||
"""
|
||||
合并另一个堆
|
||||
@type other MinHeap
|
||||
"""
|
||||
for elem in other.h:
|
||||
self.add(elem)
|
||||
|
||||
def reset(self):
|
||||
self.h = []
|
||||
heapify(self.h)
|
||||
@@ -0,0 +1,182 @@
|
||||
from copy import copy
|
||||
from dataclasses import Field
|
||||
import re
|
||||
from typing import dict
|
||||
from typing_extensions import Self
|
||||
|
||||
|
||||
class Store:
|
||||
def __init__(self, initState: dict[str, Field] = {}):
|
||||
self.__states: dict[str, Field] = initState.copy()
|
||||
self.last_state = None
|
||||
pass
|
||||
|
||||
# 设置值
|
||||
def set(self, key: str, value: any):
|
||||
field = self.__get_field__(key)
|
||||
field.setValue(value)
|
||||
return self
|
||||
|
||||
# 获取值
|
||||
def get(self, key: str, defaultValue: any = None):
|
||||
field = self.__get_field__(key)
|
||||
_value = field.getValue()
|
||||
if _value is None:
|
||||
_value = defaultValue
|
||||
return _value
|
||||
|
||||
def __getitem__(self, __key: str):
|
||||
return self.get(__key)
|
||||
|
||||
# 获取一个克隆值
|
||||
def clone(self, key: str, defaultValue: any = None):
|
||||
value = self.get(key, defaultValue)
|
||||
return copy(value)
|
||||
|
||||
# 主动通知变化
|
||||
def emit(self, key: str, value: any = None):
|
||||
field = self.__get_field__(key)
|
||||
field.emit(value)
|
||||
return self
|
||||
|
||||
# 找到首个不为空的值
|
||||
def first(self, *names):
|
||||
value = None
|
||||
for name in names:
|
||||
value = self.get(name)
|
||||
if value is not None:
|
||||
break
|
||||
return value
|
||||
|
||||
# 计算属性
|
||||
def compute(self, key: str, getter, setter=None):
|
||||
field = self.__get_field__(key)
|
||||
field.apply(setter)
|
||||
field.getter = getter
|
||||
return self
|
||||
|
||||
# 获取值并设置值
|
||||
def use(self, key: str, handle):
|
||||
if callable(handle):
|
||||
value = handle(self.get(key))
|
||||
self.set(key, value)
|
||||
return self
|
||||
|
||||
# 批量修改整个集合
|
||||
def convert(self, key: str, handle):
|
||||
return self.use(key, lambda value: list(map(handle, value)))
|
||||
|
||||
# 绑定对象的属性
|
||||
def bind(self, obj: object, name: str, key=None, defaultValue: any = None):
|
||||
def getter():
|
||||
return getattr(obj, name)
|
||||
|
||||
def setter(value):
|
||||
setattr(obj, name, value)
|
||||
|
||||
# 如果属性不存在 则初始化
|
||||
if hasattr(obj, name) is False or defaultValue is not None:
|
||||
setattr(obj, name, defaultValue)
|
||||
|
||||
return self.compute(key, getter, setter)
|
||||
|
||||
# 根据指定的条件删除
|
||||
def delete(self, pattern=None):
|
||||
def match(_):
|
||||
return True
|
||||
|
||||
if pattern is not None:
|
||||
if callable(pattern):
|
||||
match = pattern
|
||||
elif isinstance(pattern, str):
|
||||
|
||||
def match(s):
|
||||
return re.match(pattern, s)
|
||||
|
||||
keys = list(filter(match, self.__states.keys()))
|
||||
for key in keys:
|
||||
self.__states.pop(key)
|
||||
return self
|
||||
|
||||
# 根据指定的条件导出
|
||||
def exports(self, match=lambda _: True):
|
||||
result = {}
|
||||
for key in self.__states.keys():
|
||||
if match(key):
|
||||
result[key] = self.get(key)
|
||||
return result
|
||||
|
||||
# 导入
|
||||
def imports(self, pairs: dict = {}, prefix=''):
|
||||
for key in pairs.keys():
|
||||
self.set(prefix + str(key), pairs[key])
|
||||
return self
|
||||
|
||||
def copy(self) -> Self:
|
||||
return Store(self.__states)
|
||||
|
||||
# 只读属性
|
||||
|
||||
def const(self, key: str, value: any):
|
||||
return self.compute(key, lambda: value)
|
||||
|
||||
# 监听值的变化
|
||||
def watch(self, key: str, valueChanged):
|
||||
return self.compute(key, None, valueChanged)
|
||||
|
||||
def linstener(self, key: str):
|
||||
def change(value):
|
||||
self.set(key, value)
|
||||
pass
|
||||
|
||||
return change
|
||||
|
||||
def __get_field__(self, key: str):
|
||||
field = None
|
||||
if re.search(r'\{\w+\}', key):
|
||||
key = key.format_map(self)
|
||||
if self.__states.__contains__(key):
|
||||
field = self.__states[key]
|
||||
else:
|
||||
field = Store.Field()
|
||||
self.__states[key] = field
|
||||
self.last_state = (key, field)
|
||||
return field
|
||||
|
||||
class Field:
|
||||
def __init__(self, value=None):
|
||||
self.__value = None
|
||||
self.getter = None
|
||||
self.valueChangeds = []
|
||||
self.locked = False
|
||||
self.setValue(value)
|
||||
pass
|
||||
|
||||
def setValue(self, value):
|
||||
if self.locked:
|
||||
return
|
||||
self.locked = True
|
||||
self.__value = value
|
||||
self.emit(value)
|
||||
self.locked = False
|
||||
return self
|
||||
|
||||
def getValue(self):
|
||||
if callable(self.getter):
|
||||
self.__value = self.getter()
|
||||
return self.__value
|
||||
|
||||
def emit(self, value=None):
|
||||
if value is None:
|
||||
value = self.getValue()
|
||||
for valueChanged in self.valueChangeds:
|
||||
if callable(valueChanged):
|
||||
valueChanged(value)
|
||||
return
|
||||
|
||||
def apply(self, valueChanged):
|
||||
if callable(valueChanged):
|
||||
self.valueChangeds.append(valueChanged)
|
||||
|
||||
|
||||
store = Store()
|
||||
@@ -0,0 +1,58 @@
|
||||
from numbers import Number
|
||||
|
||||
|
||||
def is_number(num_str):
|
||||
"""
|
||||
判断数据是否为一个数字
|
||||
|
||||
:param num_str: 字符串对象
|
||||
:return:
|
||||
"""
|
||||
"""
|
||||
判断数据是否为一个数字
|
||||
|
||||
:param num_str: 字符串对象
|
||||
:return: 布尔值 True 是一个数字 False 不是一个数字 None 本就是数值类型
|
||||
"""
|
||||
# 防止非字段类型类型输入报错
|
||||
if isinstance(num_str, Number):
|
||||
return None
|
||||
elif not isinstance(num_str, str):
|
||||
return False
|
||||
|
||||
if num_str.isdigit():
|
||||
return True
|
||||
# 对Float类型的数字进行判断
|
||||
if num_str.count('.') == 1:
|
||||
num_str_list = num_str.split('.')
|
||||
left = num_str_list[0]
|
||||
right = num_str_list[1]
|
||||
if left.startswith('-') and left.count('-') == 1 and right.isdigit():
|
||||
_left = left.split('-')[1]
|
||||
if _left.isdigit():
|
||||
return True
|
||||
elif left.isdigit() and right.isdigit():
|
||||
return True
|
||||
# 负数判断
|
||||
elif num_str.startswith('-'):
|
||||
_left = num_str.split('-')[1]
|
||||
if _left.isdigit():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def str_to_num(value, default=0, num_type=float):
|
||||
"""
|
||||
将字符串类型转化为数据类型
|
||||
|
||||
:param value: 需要转化的值,不一定需要是字符串类型
|
||||
:param default: 设置转换失败返回数值,默认原值
|
||||
:param num_type: 设置转换成的数据类型
|
||||
:return:
|
||||
"""
|
||||
num_flag = is_number(value)
|
||||
if num_flag:
|
||||
return num_type(value)
|
||||
elif num_flag is None:
|
||||
return num_type(value)
|
||||
return value if default is None else default
|
||||
@@ -0,0 +1,211 @@
|
||||
[
|
||||
{
|
||||
"name": "swordman_male",
|
||||
"title": "鬼剑士(男)",
|
||||
"children": [
|
||||
{ "title": "极诣·剑魂", "name": "weapon_master", "open": true },
|
||||
{ "name": "soul_bender", "title": "极诣·鬼泣", "open": true },
|
||||
{ "name": "berserker", "title": "极诣·狂战士", "open": true },
|
||||
{ "name": "asura", "title": "极诣·阿修罗", "open": true },
|
||||
{ "name": "ghostblade", "title": "极诣·剑影", "open": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "swordman_female",
|
||||
"title": "鬼剑士(女)",
|
||||
"children": [
|
||||
{ "name": "sword_master", "title": "极诣·驭剑士", "open": true },
|
||||
{ "name": "dark_templar", "title": "极诣·暗殿骑士", "open": true },
|
||||
{ "name": "demon_slayer", "title": "极诣·契魔者", "open": true },
|
||||
{ "name": "vegabond", "title": "极诣·流浪武士", "open": true },
|
||||
{ "name": "spectre", "title": "极诣·刃影", "open": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fighter_male",
|
||||
"title": "格斗家(男)",
|
||||
"children": [
|
||||
{ "name": "nenmaster_male", "title": "归元·气功师", "open": true },
|
||||
{ "name": "striker_male", "title": "归元·散打", "open": true },
|
||||
{ "name": "brawler_male", "title": "归元·街霸", "open": true },
|
||||
{ "name": "grappler_male", "title": "归元·柔道家", "open": true },
|
||||
{ "name": "empty", "title": "", "comment": "首页" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fighter_female",
|
||||
"title": "格斗家(女)",
|
||||
"children": [
|
||||
{ "name": "nenmaster_female", "title": "归元·气功师", "open": true },
|
||||
{ "name": "striker_female", "title": "归元·散打", "open": true },
|
||||
{ "name": "brawler_female", "title": "归元·街霸", "open": true },
|
||||
{ "name": "grappler_female", "title": "归元·柔道家", "open": true },
|
||||
{ "name": "empty", "title": "", "comment": "设置" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gunner_male",
|
||||
"title": "神枪手(男)",
|
||||
"children": [
|
||||
{ "name": "ranger_male", "title": "重霄·漫游枪手", "open": true },
|
||||
{ "name": "launcher_male", "title": "重霄·枪炮师", "open": true },
|
||||
{ "name": "mechanic_male", "title": "重霄·机械师", "open": true },
|
||||
{ "name": "spitfire_male", "title": "重霄·弹药专家", "open": true },
|
||||
{ "name": "assault", "title": "重霄·合金战士", "open": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gunner_female",
|
||||
"title": "神枪手(女)",
|
||||
"children": [
|
||||
{ "name": "ranger_female", "title": "重霄·漫游枪手", "open": true },
|
||||
{ "name": "launcher_female", "title": "重霄·枪炮师", "open": true },
|
||||
{ "name": "mechanic_female", "title": "重霄·机械师", "open": true },
|
||||
{ "name": "spitfire_female", "title": "重霄·弹药专家", "open": true },
|
||||
{
|
||||
"name": "sponsor",
|
||||
"url": "https://bbs.colg.cn",
|
||||
"title": "",
|
||||
"open": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mage_male",
|
||||
"title": "魔法师(男)",
|
||||
"children": [
|
||||
{ "name": "elemental_bomber", "title": "知源·元素爆破师", "open": true },
|
||||
{ "name": "glacial_master", "title": "知源·冰结师", "open": true },
|
||||
{ "name": "blood_mage", "title": "知源·血法师", "open": true },
|
||||
{ "name": "swift_master", "title": "知源·逐风者", "open": true },
|
||||
{ "name": "dimension_walker", "title": "知源·次元行者", "open": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mage_female",
|
||||
"title": "魔法师(女)",
|
||||
"children": [
|
||||
{ "name": "elementalist", "title": "知源·元素师", "open": true },
|
||||
{ "name": "summoner", "title": "知源·召唤师", "open": true },
|
||||
{ "name": "battle_mage", "title": "知源·战斗法师", "open": true },
|
||||
{ "name": "witch", "title": "知源·魔道学者", "open": true },
|
||||
{
|
||||
"name": "enchantress",
|
||||
"title": "知源·小魔女",
|
||||
"open": true,
|
||||
"options": [
|
||||
{ "name": "default", "title": "奶", "class": "enchantress" },
|
||||
{ "name": "default", "title": "输出", "class": "enchantress_carry" }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "priest_male",
|
||||
"title": "圣职者(男)",
|
||||
"children": [
|
||||
{
|
||||
"name": "crusader_male",
|
||||
"title": "神启·圣骑士",
|
||||
"open": true,
|
||||
"options": [
|
||||
{ "name": "default", "title": "奶", "class": "crusader_male" },
|
||||
{ "name": "default", "title": "审判", "class": "crusader_male_carry" }
|
||||
]
|
||||
},
|
||||
{ "name": "infighter", "title": "神启·蓝拳圣使", "open": true },
|
||||
{ "name": "exorcist", "title": "神启·驱魔师", "open": true },
|
||||
{ "name": "avenger", "title": "神启·复仇者", "open": true },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "priest_female",
|
||||
"title": "圣职者(女)",
|
||||
"children": [
|
||||
{
|
||||
"name": "crusader_female",
|
||||
"title": "神启·圣骑士",
|
||||
"open": true,
|
||||
"options": [
|
||||
{ "name": "default", "title": "奶", "class": "crusader_female" },
|
||||
{
|
||||
"name": "default",
|
||||
"title": "输出",
|
||||
"class": "crusader_female_carry"
|
||||
}
|
||||
]
|
||||
},
|
||||
{ "name": "inquistor", "title": "神启·异端审判者", "open": true },
|
||||
{ "name": "sorceress", "title": "神启·巫女", "open": true },
|
||||
{ "name": "mistress", "title": "神启·诱魔者", "open": true },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "thief",
|
||||
"title": "暗夜使者",
|
||||
"children": [
|
||||
{ "name": "rogue", "title": "隐夜·刺客", "open": true },
|
||||
{ "name": "necro", "title": "隐夜·死灵术士", "open": true },
|
||||
{ "name": "kunoichi", "title": "隐夜·忍者", "open": true },
|
||||
{ "name": "shadow_dancer", "title": "隐夜·影舞者", "open": true },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "knight",
|
||||
"title": "守护者",
|
||||
"children": [
|
||||
{ "name": "elven_knight", "title": "皓曦·精灵骑士", "open": true },
|
||||
{ "name": "chaos", "title": "皓曦·混沌魔灵", "open": true },
|
||||
{ "name": "paladin", "title": "皓曦·帕拉丁", "open": true },
|
||||
{ "name": "dragon_knight", "title": "皓曦·龙骑士", "open": true },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "demonic_lancer",
|
||||
"title": "魔枪士",
|
||||
"children": [
|
||||
{ "name": "vanguard", "title": "千魂·征战者", "open": true },
|
||||
{ "name": "skirmisher", "title": "千魂·决战者", "open": true },
|
||||
{ "name": "dragoon", "title": "千魂·狩猎者", "open": true },
|
||||
{ "name": "impaler", "title": "千魂·暗枪士", "open": true },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gunblader",
|
||||
"title": "枪剑士",
|
||||
"children": [
|
||||
{ "name": "hitman", "title": "苍暮·暗刃", "open": true },
|
||||
{ "name": "agent", "title": "苍暮·特工", "open": true },
|
||||
{ "name": "trouble_shooter", "title": "苍暮·战线佣兵", "open": true },
|
||||
{ "name": "specialist", "title": "苍暮·源能专家", "open": true },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "archer",
|
||||
"title": "弓箭手",
|
||||
"children": [
|
||||
{ "name": "muse", "title": "聆风·缪斯", "open": true },
|
||||
{ "name": "traveler", "title": "聆风·旅人", "open": true },
|
||||
{ "name": "hunter", "title": "聆风·猎人", "open": true },
|
||||
{ "name": "vigilante", "title": "聆风·妖护使", "open": true },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "extra",
|
||||
"title": "外传",
|
||||
"children": [
|
||||
{ "name": "creator", "title": "知源·缔造者", "open": true },
|
||||
{ "name": "dark_knight", "title": "极诣·黑暗武士", "open": true },
|
||||
{ "name": "empty", "title": "" },
|
||||
{ "name": "empty", "title": "" },
|
||||
{ "name": "empty", "title": "" }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
import redis
|
||||
|
||||
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
|
||||
@@ -0,0 +1,23 @@
|
||||
import os
|
||||
import sys
|
||||
import redis
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import Session
|
||||
from config.main import config
|
||||
|
||||
RedisPool = redis.ConnectionPool.from_url(config.REDIS_URL)
|
||||
|
||||
def get_redis():
|
||||
with redis.Redis(connection_pool=RedisPool) as redis_conn:
|
||||
yield redis_conn
|
||||
|
||||
def get_db_engine(version='0'):
|
||||
try:
|
||||
os.chdir(os.path.dirname(sys.argv[0]))
|
||||
except Exception:
|
||||
pass
|
||||
return create_engine(f'sqlite:///{os.path.join("./", "dataFiles", f"dcalc_{version}.db")}')
|
||||
|
||||
def get_db():
|
||||
with Session(get_db_engine()) as session:
|
||||
yield session
|
||||
@@ -0,0 +1,55 @@
|
||||
# import os
|
||||
# import sys
|
||||
from sqlalchemy import Column, Integer, Text, Float
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
Base = declarative_base()
|
||||
metadata = Base.metadata
|
||||
|
||||
|
||||
class SuitData(Base):
|
||||
__tablename__ = 'suit'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
suitId = Column(Integer)
|
||||
suitName = Column(Text)
|
||||
rarity = Column(Text)
|
||||
name = Column(Text)
|
||||
point = Column(Integer)
|
||||
level = Column(Integer)
|
||||
count = Column(Integer)
|
||||
SkillAttack = Column(Float)
|
||||
Attack = Column(Float)
|
||||
|
||||
|
||||
class EquData(Base):
|
||||
"""
|
||||
装备属性映射
|
||||
首字母大写的属性为调适可能会影响到的属性
|
||||
"""
|
||||
|
||||
__tablename__ = 'equ'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(Text)
|
||||
rarity = Column(Text)
|
||||
itemType = Column(Text)
|
||||
itemDetailType = Column(Text)
|
||||
Point = Column(Text)
|
||||
categorize = Column(Text)
|
||||
imageUrl = Column(Text)
|
||||
detail = Column(Text)
|
||||
bufferDetail = Column(Text)
|
||||
STR = Column(Text)
|
||||
INT = Column(Text)
|
||||
Vitality = Column(Text)
|
||||
Spirit = Column(Text)
|
||||
AtkP = Column(Text)
|
||||
AtkM = Column(Text)
|
||||
AtkI = Column(Text)
|
||||
SkillAttack = Column(Text)
|
||||
Attack = Column(Text)
|
||||
Buffer = Column(Text)
|
||||
suit = Column(Text)
|
||||
@@ -0,0 +1,25 @@
|
||||
from config.main import config
|
||||
from api.main import api_router
|
||||
from fastapi import FastAPI
|
||||
from multiprocessing import freeze_support
|
||||
from api.core import Exceptions,Middleware,Gzip
|
||||
import uvicorn
|
||||
|
||||
if __name__ == '__main__':
|
||||
freeze_support()
|
||||
|
||||
def on_startup():
|
||||
return print("Application starting...")
|
||||
|
||||
application = FastAPI(docs_url=None, redoc_url=None)
|
||||
|
||||
application.add_exception_handler(Exception, Exceptions.all_exception_handler)
|
||||
|
||||
Middleware.register_cors(application)
|
||||
Gzip.register_gzip_response(application)
|
||||
|
||||
application.include_router(api_router)
|
||||
|
||||
uvicorn.run(application, host='127.0.0.1', port=config.PORT)
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[project]
|
||||
name = "dcalc-backend"
|
||||
version = "0.1.0"
|
||||
description = "A backend project for dcalc, a calculator application."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"fastapi[all]>=0.115.11",
|
||||
"redis>=5.2.1",
|
||||
"requests>=2.32.3",
|
||||
"sqlalchemy>=2.0.38",
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
# 限制每行最多20个字符
|
||||
line-length = 200
|
||||
lint.select = ["F","E","W","UP"]
|
||||
|
||||
[format]
|
||||
# 使用单引号
|
||||
quote-style = "single"
|
||||
# 缩进使用两个空格
|
||||
indent-style = "space"
|
||||
@@ -0,0 +1,87 @@
|
||||
from core.character.GF.gunner_female.spitfire_female import classChange
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# print(equs.equ_dict["100161036"].adapt(2).adapt(0).Point)
|
||||
char = classChange(0)
|
||||
print(char.getInfo())
|
||||
char.calc_init(
|
||||
{
|
||||
'equips': {
|
||||
'武器': {
|
||||
'id': '85',
|
||||
'reinforce': 1,
|
||||
'reinforceType': 1,
|
||||
'enchant': '1',
|
||||
'emblems': ['1'],
|
||||
'upgrade': 1,
|
||||
'refine': 1,
|
||||
'upgradeDetail': {'1': 1},
|
||||
'adaptation': 1,
|
||||
},
|
||||
'上衣': {
|
||||
'id': '855',
|
||||
'reinforce': 1,
|
||||
'reinforceType': 1,
|
||||
'enchant': '1',
|
||||
'emblems': ['1'],
|
||||
'upgrade': 1,
|
||||
'refine': 1,
|
||||
'upgradeDetail': {'1': 1},
|
||||
'adaptation': 0,
|
||||
},
|
||||
},
|
||||
'skills': {'1': {'lv': 20}, '5': {'lv': 10}},
|
||||
}
|
||||
)
|
||||
手雷精通 = char.GetSkillByName('手雷精通')
|
||||
G14手雷 = char.GetSkillByName('G-14手雷')
|
||||
print(手雷精通.lv, G14手雷.lv)
|
||||
print(char.GetSkillByName('G-14手雷').skillInfo())
|
||||
print(char.charEquipInfo['武器'].equInfo.name)
|
||||
# # 当前适用的套装搜索
|
||||
# suitId = 16201
|
||||
# point = 2345
|
||||
|
||||
# suits = equs.get_suit_info(suitId, point,0)
|
||||
|
||||
# print(suits[0].__dict__)
|
||||
|
||||
# class A:
|
||||
# def __init__(self):
|
||||
# self.a = 1
|
||||
# self.b = 2
|
||||
# self.skills:list[B] = []
|
||||
|
||||
# def __str__(self):
|
||||
# return f"{self.a} {self.b}"
|
||||
|
||||
# def __repr__(self):
|
||||
# return f"{self.a} {self.b}"
|
||||
|
||||
# class B:
|
||||
|
||||
# _lv = 0
|
||||
|
||||
# def __init__(self,char):
|
||||
# self.char = char
|
||||
# self.lv = 1
|
||||
|
||||
# @property
|
||||
# def lv(self):
|
||||
# return self._lv
|
||||
|
||||
# @lv.setter
|
||||
# def lv(self, value):
|
||||
# if self._lv != value:
|
||||
# self.effect(self._lv,value)
|
||||
# self._lv = value
|
||||
|
||||
# def effect(self,old,new):
|
||||
# self.char.a += new - old
|
||||
|
||||
# a = A()
|
||||
# b = B(a)
|
||||
# a.skills.append(b)
|
||||
# b.lv += 1
|
||||
# print(a.a)
|
||||
@@ -0,0 +1,686 @@
|
||||
version = 1
|
||||
revision = 1
|
||||
requires-python = ">=3.13"
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
version = "0.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "idna" },
|
||||
{ name = "sniffio" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a3/73/199a98fc2dae33535d6b8e8e6ec01f8c1d76c9adb096c6b7d64823038cde/anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", size = 181126 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2025.1.31"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.4.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dcalc-backend"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "fastapi", extra = ["all"] },
|
||||
{ name = "redis" },
|
||||
{ name = "requests" },
|
||||
{ name = "sqlalchemy" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "fastapi", extras = ["all"], specifier = ">=0.115.11" },
|
||||
{ name = "redis", specifier = ">=5.2.1" },
|
||||
{ name = "requests", specifier = ">=2.32.3" },
|
||||
{ name = "sqlalchemy", specifier = ">=2.0.38" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dnspython"
|
||||
version = "2.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b5/4a/263763cb2ba3816dd94b08ad3a33d5fdae34ecb856678773cc40a3605829/dnspython-2.7.0.tar.gz", hash = "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1", size = 345197 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/68/1b/e0a87d256e40e8c888847551b20a017a6b98139178505dc7ffb96f04e954/dnspython-2.7.0-py3-none-any.whl", hash = "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", size = 313632 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "email-validator"
|
||||
version = "2.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "dnspython" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/48/ce/13508a1ec3f8bb981ae4ca79ea40384becc868bfae97fd1c942bb3a001b1/email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7", size = 48967 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/ee/bf0adb559ad3c786f12bcbc9296b3f5675f529199bef03e2df281fa1fadb/email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", size = 33521 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi"
|
||||
version = "0.115.11"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "starlette" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b5/28/c5d26e5860df807241909a961a37d45e10533acef95fc368066c7dd186cd/fastapi-0.115.11.tar.gz", hash = "sha256:cc81f03f688678b92600a65a5e618b93592c65005db37157147204d8924bf94f", size = 294441 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/5d/4d8bbb94f0dbc22732350c06965e40740f4a92ca560e90bb566f4f73af41/fastapi-0.115.11-py3-none-any.whl", hash = "sha256:32e1541b7b74602e4ef4a0260ecaf3aadf9d4f19590bba3e1bf2ac4666aa2c64", size = 94926 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
all = [
|
||||
{ name = "email-validator" },
|
||||
{ name = "fastapi-cli", extra = ["standard"] },
|
||||
{ name = "httpx" },
|
||||
{ name = "itsdangerous" },
|
||||
{ name = "jinja2" },
|
||||
{ name = "orjson" },
|
||||
{ name = "pydantic-extra-types" },
|
||||
{ name = "pydantic-settings" },
|
||||
{ name = "python-multipart" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "ujson" },
|
||||
{ name = "uvicorn", extra = ["standard"] },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi-cli"
|
||||
version = "0.0.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "rich-toolkit" },
|
||||
{ name = "typer" },
|
||||
{ name = "uvicorn", extra = ["standard"] },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fe/73/82a5831fbbf8ed75905bacf5b2d9d3dfd6f04d6968b29fe6f72a5ae9ceb1/fastapi_cli-0.0.7.tar.gz", hash = "sha256:02b3b65956f526412515907a0793c9094abd4bfb5457b389f645b0ea6ba3605e", size = 16753 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/e6/5daefc851b514ce2287d8f5d358ae4341089185f78f3217a69d0ce3a390c/fastapi_cli-0.0.7-py3-none-any.whl", hash = "sha256:d549368ff584b2804336c61f192d86ddea080c11255f375959627911944804f4", size = 10705 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
standard = [
|
||||
{ name = "uvicorn", extra = ["standard"] },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "greenlet"
|
||||
version = "3.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2f/ff/df5fede753cc10f6a5be0931204ea30c35fa2f2ea7a35b25bdaf4fe40e46/greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", size = 186022 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/57/0db4940cd7bb461365ca8d6fd53e68254c9dbbcc2b452e69d0d41f10a85e/greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", size = 272990 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/ec/423d113c9f74e5e402e175b157203e9102feeb7088cee844d735b28ef963/greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", size = 649175 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/46/ddbd2db9ff209186b7b7c621d1432e2f21714adc988703dbdd0e65155c77/greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", size = 663425 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/f9/9c82d6b2b04aa37e38e74f0c429aece5eeb02bab6e3b98e7db89b23d94c6/greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", size = 657736 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/42/b87bc2a81e3a62c3de2b0d550bf91a86939442b7ff85abb94eec3fc0e6aa/greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", size = 660347 },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/fa/71599c3fd06336cdc3eac52e6871cfebab4d9d70674a9a9e7a482c318e99/greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", size = 615583 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/96/e9ef85de031703ee7a4483489b40cf307f93c1824a02e903106f2ea315fe/greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", size = 1133039 },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/76/b2b6362accd69f2d1889db61a18c94bc743e961e3cab344c2effaa4b4a25/greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", size = 1160716 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/1b/54336d876186920e185066d8c3024ad55f21d7cc3683c856127ddb7b13ce/greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", size = 299490 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/17/bea55bf36990e1638a2af5ba10c1640273ef20f627962cf97107f1e5d637/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", size = 643731 },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/d2/aa3d2157f9ab742a08e0fd8f77d4699f37c22adfbfeb0c610a186b5f75e0/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", size = 649304 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/8e/d0aeffe69e53ccff5a28fa86f07ad1d2d2d6537a9506229431a2a02e2f15/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", size = 646537 },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/79/e15408220bbb989469c8871062c97c6c9136770657ba779711b90870d867/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", size = 642506 },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/87/470e01a940307796f1d25f8167b551a968540fbe0551c0ebb853cb527dd6/greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", size = 602753 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/72/576815ba674eddc3c25028238f74d7b8068902b3968cbe456771b166455e/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", size = 1122731 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/38/08cc303ddddc4b3d7c628c3039a61a3aae36c241ed01393d00c2fd663473/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", size = 1142112 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httptools"
|
||||
version = "0.6.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121 },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.28.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "certifi" },
|
||||
{ name = "httpcore" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "2.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinja2"
|
||||
version = "3.1.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markupsafe" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "3.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mdurl" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101 },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603 },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486 },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914 },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098 },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdurl"
|
||||
version = "0.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "orjson"
|
||||
version = "3.10.15"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/5dea21763eeff8c1590076918a446ea3d6140743e0e36f58f369928ed0f4/orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e", size = 5282482 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/06/10/fe7d60b8da538e8d3d3721f08c1b7bff0491e8fa4dd3bf11a17e34f4730e/orjson-3.10.15-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bae0e6ec2b7ba6895198cd981b7cca95d1487d0147c8ed751e5632ad16f031a6", size = 249399 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/83/52c356fd3a61abd829ae7e4366a6fe8e8863c825a60d7ac5156067516edf/orjson-3.10.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93ce145b2db1252dd86af37d4165b6faa83072b46e3995ecc95d4b2301b725a", size = 125044 },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/b2/d06d5901408e7ded1a74c7c20d70e3a127057a6d21355f50c90c0f337913/orjson-3.10.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c203f6f969210128af3acae0ef9ea6aab9782939f45f6fe02d05958fe761ef9", size = 150066 },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/8c/60c3106e08dc593a861755781c7c675a566445cc39558677d505878d879f/orjson-3.10.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8918719572d662e18b8af66aef699d8c21072e54b6c82a3f8f6404c1f5ccd5e0", size = 139737 },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/8c/ae00d7d0ab8a4490b1efeb01ad4ab2f1982e69cc82490bf8093407718ff5/orjson-3.10.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f71eae9651465dff70aa80db92586ad5b92df46a9373ee55252109bb6b703307", size = 154804 },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/86/65dc69bd88b6dd254535310e97bc518aa50a39ef9c5a2a5d518e7a223710/orjson-3.10.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e117eb299a35f2634e25ed120c37c641398826c2f5a3d3cc39f5993b96171b9e", size = 130583 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/00/6fe01ededb05d52be42fabb13d93a36e51f1fd9be173bd95707d11a8a860/orjson-3.10.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13242f12d295e83c2955756a574ddd6741c81e5b99f2bef8ed8d53e47a01e4b7", size = 138465 },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/2f/4cc151c4b471b0cdc8cb29d3eadbce5007eb0475d26fa26ed123dca93b33/orjson-3.10.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7946922ada8f3e0b7b958cc3eb22cfcf6c0df83d1fe5521b4a100103e3fa84c8", size = 130742 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/13/8a6109e4b477c518498ca37963d9c0eb1508b259725553fb53d53b20e2ea/orjson-3.10.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b7155eb1623347f0f22c38c9abdd738b287e39b9982e1da227503387b81b34ca", size = 414669 },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/7b/1d229d6d24644ed4d0a803de1b0e2df832032d5beda7346831c78191b5b2/orjson-3.10.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:208beedfa807c922da4e81061dafa9c8489c6328934ca2a562efa707e049e561", size = 141043 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/d3/6dc91156cf12ed86bed383bcb942d84d23304a1e57b7ab030bf60ea130d6/orjson-3.10.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eca81f83b1b8c07449e1d6ff7074e82e3fd6777e588f1a6632127f286a968825", size = 129826 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/38/c47c25b86f6996f1343be721b6ea4367bc1c8bc0fc3f6bbcd995d18cb19d/orjson-3.10.15-cp313-cp313-win32.whl", hash = "sha256:c03cd6eea1bd3b949d0d007c8d57049aa2b39bd49f58b4b2af571a5d3833d890", size = 142542 },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/f1/1d7ec15b20f8ce9300bc850de1e059132b88990e46cd0ccac29cbf11e4f9/orjson-3.10.15-cp313-cp313-win_amd64.whl", hash = "sha256:fd56a26a04f6ba5fb2045b0acc487a63162a958ed837648c5781e1fe3316cfbf", size = 133444 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.10.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
{ name = "pydantic-core" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.27.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-extra-types"
|
||||
version = "2.10.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/23/ed/69f3f3de12c02ebd58b2f66ffb73d0f5a1b10b322227897499753cebe818/pydantic_extra_types-2.10.2.tar.gz", hash = "sha256:934d59ab7a02ff788759c3a97bc896f5cfdc91e62e4f88ea4669067a73f14b98", size = 86893 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/08/da/86bc9addde8a24348ac15f8f7dcb853f78e9573c7667800dd9bc60558678/pydantic_extra_types-2.10.2-py3-none-any.whl", hash = "sha256:9eccd55a2b7935cea25f0a67f6ff763d55d80c41d86b887d88915412ccf5b7fa", size = 35473 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-settings"
|
||||
version = "2.8.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pydantic" },
|
||||
{ name = "python-dotenv" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/88/82/c79424d7d8c29b994fb01d277da57b0a9b09cc03c3ff875f9bd8a86b2145/pydantic_settings-2.8.1.tar.gz", hash = "sha256:d5c663dfbe9db9d5e1c646b2e161da12f0d734d422ee56f567d0ea2cee4e8585", size = 83550 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/53/a64f03044927dc47aafe029c42a5b7aabc38dfb813475e0e1bf71c4a59d0/pydantic_settings-2.8.1-py3-none-any.whl", hash = "sha256:81942d5ac3d905f7f3ee1a70df5dfb62d5569c12f51a5a647defc1c3d9ee2e9c", size = 30839 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.19.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-multipart"
|
||||
version = "0.0.20"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redis"
|
||||
version = "5.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/47/da/d283a37303a995cd36f8b92db85135153dc4f7a8e4441aa827721b442cfb/redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f", size = 4608355 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "charset-normalizer" },
|
||||
{ name = "idna" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "13.9.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markdown-it-py" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rich-toolkit"
|
||||
version = "0.13.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "rich" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5b/8a/71cfbf6bf6257ea785d1f030c22468f763eea1b3e5417620f2ba9abd6dca/rich_toolkit-0.13.2.tar.gz", hash = "sha256:fea92557530de7c28f121cbed572ad93d9e0ddc60c3ca643f1b831f2f56b95d3", size = 72288 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/1b/1c2f43af46456050b27810a7a013af8a7e12bc545a0cdc00eb0df55eb769/rich_toolkit-0.13.2-py3-none-any.whl", hash = "sha256:f3f6c583e5283298a2f7dbd3c65aca18b7f818ad96174113ab5bec0b0e35ed61", size = 13566 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellingham"
|
||||
version = "1.5.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
version = "2.0.38"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "greenlet", marker = "(python_full_version < '3.14' and platform_machine == 'AMD64') or (python_full_version < '3.14' and platform_machine == 'WIN32') or (python_full_version < '3.14' and platform_machine == 'aarch64') or (python_full_version < '3.14' and platform_machine == 'amd64') or (python_full_version < '3.14' and platform_machine == 'ppc64le') or (python_full_version < '3.14' and platform_machine == 'win32') or (python_full_version < '3.14' and platform_machine == 'x86_64')" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e4/08/9a90962ea72acd532bda71249a626344d855c4032603924b1b547694b837/sqlalchemy-2.0.38.tar.gz", hash = "sha256:e5a4d82bdb4bf1ac1285a68eab02d253ab73355d9f0fe725a97e1e0fa689decb", size = 9634782 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/21/77/caa875a1f5a8a8980b564cc0e6fee1bc992d62d29101252561d0a5e9719c/SQLAlchemy-2.0.38-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ecef029b69843b82048c5b347d8e6049356aa24ed644006c9a9d7098c3bd3bfd", size = 2100201 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/ec/94bb036ec78bf9a20f8010c807105da9152dd84f72e8c51681ad2f30b3fd/SQLAlchemy-2.0.38-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c8bcad7fc12f0cc5896d8e10fdf703c45bd487294a986903fe032c72201596b", size = 2090678 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/61/63ff1893f146e34d3934c0860209fdd3925c25ee064330e6c2152bacc335/SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0ef3f98175d77180ffdc623d38e9f1736e8d86b6ba70bff182a7e68bed7727", size = 3177107 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/4f/b933bea41a602b5f274065cc824fae25780ed38664d735575192490a021b/SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ac78898c50e2574e9f938d2e5caa8fe187d7a5b69b65faa1ea4648925b096", size = 3190435 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/23/9e654b4059e385988de08c5d3b38a369ea042f4c4d7c8902376fd737096a/SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9eb4fa13c8c7a2404b6a8e3772c17a55b1ba18bc711e25e4d6c0c9f5f541b02a", size = 3123648 },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/59/94c6d804e76ebc6412a08d2b086a8cb3e5a056cd61508e18ddaf3ec70100/SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5dba1cdb8f319084f5b00d41207b2079822aa8d6a4667c0f369fce85e34b0c86", size = 3151789 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/27/17f143013aabbe1256dce19061eafdce0b0142465ce32168cdb9a18c04b1/SQLAlchemy-2.0.38-cp313-cp313-win32.whl", hash = "sha256:eae27ad7580529a427cfdd52c87abb2dfb15ce2b7a3e0fc29fbb63e2ed6f8120", size = 2073023 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/3e/259404b03c3ed2e7eee4c179e001a07d9b61070334be91124cf4ad32eec7/SQLAlchemy-2.0.38-cp313-cp313-win_amd64.whl", hash = "sha256:b335a7c958bc945e10c522c069cd6e5804f4ff20f9a744dd38e748eb602cbbda", size = 2096908 },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/e4/592120713a314621c692211eba034d09becaf6bc8848fabc1dc2a54d8c16/SQLAlchemy-2.0.38-py3-none-any.whl", hash = "sha256:63178c675d4c80def39f1febd625a6333f44c0ba269edd8a468b156394b27753", size = 1896347 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "starlette"
|
||||
version = "0.46.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/04/1b/52b27f2e13ceedc79a908e29eac426a63465a1a01248e5f24aa36a62aeb3/starlette-0.46.1.tar.gz", hash = "sha256:3c88d58ee4bd1bb807c0d1acb381838afc7752f9ddaec81bbe4383611d833230", size = 2580102 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/4b/528ccf7a982216885a1ff4908e886b8fb5f19862d1962f56a3fce2435a70/starlette-0.46.1-py3-none-any.whl", hash = "sha256:77c74ed9d2720138b25875133f3a2dae6d854af2ec37dceb56aef370c1d8a227", size = 71995 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typer"
|
||||
version = "0.15.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "rich" },
|
||||
{ name = "shellingham" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8b/6f/3991f0f1c7fcb2df31aef28e0594d8d54b05393a0e4e34c65e475c2a5d41/typer-0.15.2.tar.gz", hash = "sha256:ab2fab47533a813c49fe1f16b1a370fd5819099c00b119e0633df65f22144ba5", size = 100711 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/fc/5b29fea8cee020515ca82cc68e3b8e1e34bb19a3535ad854cac9257b414c/typer-0.15.2-py3-none-any.whl", hash = "sha256:46a499c6107d645a9c13f7ee46c5d5096cae6f5fc57dd11eccbbb9ae3e44ddfc", size = 45061 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.12.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ujson"
|
||||
version = "5.10.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f0/00/3110fd566786bfa542adb7932d62035e0c0ef662a8ff6544b6643b3d6fd7/ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1", size = 7154885 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/69/b3e3f924bb0e8820bb46671979770c5be6a7d51c77a66324cdb09f1acddb/ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287", size = 55646 },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/8a/9b748eb543c6cabc54ebeaa1f28035b1bd09c0800235b08e85990734c41e/ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e", size = 51806 },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/50/4b53ea234413b710a18b305f465b328e306ba9592e13a791a6a6b378869b/ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557", size = 51975 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/9d/8061934f960cdb6dd55f0b3ceeff207fcc48c64f58b43403777ad5623d9e/ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988", size = 53693 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/be/7bfa84b28519ddbb67efc8410765ca7da55e6b93aba84d97764cd5794dbc/ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816", size = 58594 },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/eb/85d465abafb2c69d9699cfa5520e6e96561db787d36c677370e066c7e2e7/ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20", size = 997853 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/76/2a63409fc05d34dd7d929357b7a45e3a2c96f22b4225cd74becd2ba6c4cb/ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0", size = 1140694 },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/ed/582c4daba0f3e1688d923b5cb914ada1f9defa702df38a1916c899f7c4d1/ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f", size = 1043580 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/0c/9837fece153051e19c7bade9f88f9b409e026b9525927824cdf16293b43b/ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165", size = 38766 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/72/6cb6728e2738c05bbe9bd522d6fc79f86b9a28402f38663e85a28fddd4a0/ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539", size = 42212 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.34.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
standard = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "httptools" },
|
||||
{ name = "python-dotenv" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" },
|
||||
{ name = "watchfiles" },
|
||||
{ name = "websockets" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvloop"
|
||||
version = "0.21.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123 },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325 },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068 },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428 },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "watchfiles"
|
||||
version = "1.0.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/26/c705fc77d0a9ecdb9b66f1e2976d95b81df3cae518967431e7dbf9b5e219/watchfiles-1.0.4.tar.gz", hash = "sha256:6ba473efd11062d73e4f00c2b730255f9c1bdd73cd5f9fe5b5da8dbd4a717205", size = 94625 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/08/98/f03efabec64b5b1fa58c0daab25c68ef815b0f320e54adcacd0d6847c339/watchfiles-1.0.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:8012bd820c380c3d3db8435e8cf7592260257b378b649154a7948a663b5f84e9", size = 390954 },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/09/4dd49ba0a32a45813debe5fb3897955541351ee8142f586303b271a02b40/watchfiles-1.0.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa216f87594f951c17511efe5912808dfcc4befa464ab17c98d387830ce07b60", size = 381133 },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/59/5aa6fc93553cd8d8ee75c6247763d77c02631aed21551a97d94998bf1dae/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62c9953cf85529c05b24705639ffa390f78c26449e15ec34d5339e8108c7c407", size = 449516 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/aa/df4b6fe14b6317290b91335b23c96b488d365d65549587434817e06895ea/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7cf684aa9bba4cd95ecb62c822a56de54e3ae0598c1a7f2065d51e24637a3c5d", size = 454820 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/71/185f8672f1094ce48af33252c73e39b48be93b761273872d9312087245f6/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f44a39aee3cbb9b825285ff979ab887a25c5d336e5ec3574f1506a4671556a8d", size = 481550 },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/d7/50ebba2c426ef1a5cb17f02158222911a2e005d401caf5d911bfca58f4c4/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38320582736922be8c865d46520c043bff350956dfc9fbaee3b2df4e1740a4b", size = 518647 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/7a/4c009342e393c545d68987e8010b937f72f47937731225b2b29b7231428f/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39f4914548b818540ef21fd22447a63e7be6e24b43a70f7642d21f1e73371590", size = 497547 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/7c/1cf50b35412d5c72d63b2bf9a4fffee2e1549a245924960dd087eb6a6de4/watchfiles-1.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f12969a3765909cf5dc1e50b2436eb2c0e676a3c75773ab8cc3aa6175c16e902", size = 452179 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/a9/3db1410e1c1413735a9a472380e4f431ad9a9e81711cda2aaf02b7f62693/watchfiles-1.0.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:0986902677a1a5e6212d0c49b319aad9cc48da4bd967f86a11bde96ad9676ca1", size = 614125 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/e1/0025d365cf6248c4d1ee4c3d2e3d373bdd3f6aff78ba4298f97b4fad2740/watchfiles-1.0.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:308ac265c56f936636e3b0e3f59e059a40003c655228c131e1ad439957592303", size = 611911 },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/55/035838277d8c98fc8c917ac9beeb0cd6c59d675dc2421df5f9fcf44a0070/watchfiles-1.0.4-cp313-cp313-win32.whl", hash = "sha256:aee397456a29b492c20fda2d8961e1ffb266223625346ace14e4b6d861ba9c80", size = 271152 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/e5/96b8e55271685ddbadc50ce8bc53aa2dff278fb7ac4c2e473df890def2dc/watchfiles-1.0.4-cp313-cp313-win_amd64.whl", hash = "sha256:d6097538b0ae5c1b88c3b55afa245a66793a8fec7ada6755322e465fb1a0e8cc", size = 285216 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websockets"
|
||||
version = "15.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440 },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329 },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111 },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496 },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217 },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195 },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 },
|
||||
]
|
||||
@@ -0,0 +1,9 @@
|
||||
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}]
|
||||
charset = utf-8
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
end_of_line = lf
|
||||
max_line_length = 100
|
||||
@@ -0,0 +1,305 @@
|
||||
{
|
||||
"globals": {
|
||||
"Component": true,
|
||||
"ComponentPublicInstance": true,
|
||||
"ComputedRef": true,
|
||||
"DirectiveBinding": true,
|
||||
"EffectScope": true,
|
||||
"ExtractDefaultPropTypes": true,
|
||||
"ExtractPropTypes": true,
|
||||
"ExtractPublicPropTypes": true,
|
||||
"InjectionKey": true,
|
||||
"MaybeRef": true,
|
||||
"MaybeRefOrGetter": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"VNode": true,
|
||||
"WritableComputedRef": true,
|
||||
"asyncComputed": true,
|
||||
"autoResetRef": true,
|
||||
"computed": true,
|
||||
"computedAsync": true,
|
||||
"computedEager": true,
|
||||
"computedInject": true,
|
||||
"computedWithControl": true,
|
||||
"controlledComputed": true,
|
||||
"controlledRef": true,
|
||||
"createApp": true,
|
||||
"createEventHook": true,
|
||||
"createGlobalState": true,
|
||||
"createInjectionState": true,
|
||||
"createReactiveFn": true,
|
||||
"createRef": true,
|
||||
"createReusableTemplate": true,
|
||||
"createSharedComposable": true,
|
||||
"createTemplatePromise": true,
|
||||
"createUnrefFn": true,
|
||||
"customRef": true,
|
||||
"debouncedRef": true,
|
||||
"debouncedWatch": true,
|
||||
"defineAsyncComponent": true,
|
||||
"defineComponent": true,
|
||||
"eagerComputed": true,
|
||||
"effectScope": true,
|
||||
"extendRef": true,
|
||||
"getCurrentInstance": true,
|
||||
"getCurrentScope": true,
|
||||
"h": true,
|
||||
"ignorableWatch": true,
|
||||
"inject": true,
|
||||
"injectLocal": true,
|
||||
"isDefined": true,
|
||||
"isProxy": true,
|
||||
"isReactive": true,
|
||||
"isReadonly": true,
|
||||
"isRef": true,
|
||||
"makeDestructurable": true,
|
||||
"markRaw": true,
|
||||
"nextTick": true,
|
||||
"onActivated": true,
|
||||
"onBeforeMount": true,
|
||||
"onBeforeRouteLeave": true,
|
||||
"onBeforeRouteUpdate": true,
|
||||
"onBeforeUnmount": true,
|
||||
"onBeforeUpdate": true,
|
||||
"onClickOutside": true,
|
||||
"onDeactivated": true,
|
||||
"onElementRemoval": true,
|
||||
"onErrorCaptured": true,
|
||||
"onKeyStroke": true,
|
||||
"onLongPress": true,
|
||||
"onMounted": true,
|
||||
"onRenderTracked": true,
|
||||
"onRenderTriggered": true,
|
||||
"onScopeDispose": true,
|
||||
"onServerPrefetch": true,
|
||||
"onStartTyping": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"onWatcherCleanup": true,
|
||||
"pausableWatch": true,
|
||||
"provide": true,
|
||||
"provideLocal": true,
|
||||
"reactify": true,
|
||||
"reactifyObject": true,
|
||||
"reactive": true,
|
||||
"reactiveComputed": true,
|
||||
"reactiveOmit": true,
|
||||
"reactivePick": true,
|
||||
"readonly": true,
|
||||
"ref": true,
|
||||
"refAutoReset": true,
|
||||
"refDebounced": true,
|
||||
"refDefault": true,
|
||||
"refThrottled": true,
|
||||
"refWithControl": true,
|
||||
"resolveComponent": true,
|
||||
"resolveRef": true,
|
||||
"resolveUnref": true,
|
||||
"shallowReactive": true,
|
||||
"shallowReadonly": true,
|
||||
"shallowRef": true,
|
||||
"syncRef": true,
|
||||
"syncRefs": true,
|
||||
"templateRef": true,
|
||||
"throttledRef": true,
|
||||
"throttledWatch": true,
|
||||
"toRaw": true,
|
||||
"toReactive": true,
|
||||
"toRef": true,
|
||||
"toRefs": true,
|
||||
"toValue": true,
|
||||
"triggerRef": true,
|
||||
"tryOnBeforeMount": true,
|
||||
"tryOnBeforeUnmount": true,
|
||||
"tryOnMounted": true,
|
||||
"tryOnScopeDispose": true,
|
||||
"tryOnUnmounted": true,
|
||||
"unref": true,
|
||||
"unrefElement": true,
|
||||
"until": true,
|
||||
"useActiveElement": true,
|
||||
"useAnimate": true,
|
||||
"useArrayDifference": true,
|
||||
"useArrayEvery": true,
|
||||
"useArrayFilter": true,
|
||||
"useArrayFind": true,
|
||||
"useArrayFindIndex": true,
|
||||
"useArrayFindLast": true,
|
||||
"useArrayIncludes": true,
|
||||
"useArrayJoin": true,
|
||||
"useArrayMap": true,
|
||||
"useArrayReduce": true,
|
||||
"useArraySome": true,
|
||||
"useArrayUnique": true,
|
||||
"useAsyncQueue": true,
|
||||
"useAsyncState": true,
|
||||
"useAttrs": true,
|
||||
"useBase64": true,
|
||||
"useBattery": true,
|
||||
"useBluetooth": true,
|
||||
"useBreakpoints": true,
|
||||
"useBroadcastChannel": true,
|
||||
"useBrowserLocation": true,
|
||||
"useCached": true,
|
||||
"useClipboard": true,
|
||||
"useClipboardItems": true,
|
||||
"useCloned": true,
|
||||
"useColorMode": true,
|
||||
"useConfirmDialog": true,
|
||||
"useCountdown": true,
|
||||
"useCounter": true,
|
||||
"useCssModule": true,
|
||||
"useCssVar": true,
|
||||
"useCssVars": true,
|
||||
"useCurrentElement": true,
|
||||
"useCycleList": true,
|
||||
"useDark": true,
|
||||
"useDateFormat": true,
|
||||
"useDebounce": true,
|
||||
"useDebounceFn": true,
|
||||
"useDebouncedRefHistory": true,
|
||||
"useDeviceMotion": true,
|
||||
"useDeviceOrientation": true,
|
||||
"useDevicePixelRatio": true,
|
||||
"useDevicesList": true,
|
||||
"useDisplayMedia": true,
|
||||
"useDocumentVisibility": true,
|
||||
"useDraggable": true,
|
||||
"useDropZone": true,
|
||||
"useElementBounding": true,
|
||||
"useElementByPoint": true,
|
||||
"useElementHover": true,
|
||||
"useElementSize": true,
|
||||
"useElementVisibility": true,
|
||||
"useEventBus": true,
|
||||
"useEventListener": true,
|
||||
"useEventSource": true,
|
||||
"useEyeDropper": true,
|
||||
"useFavicon": true,
|
||||
"useFetch": true,
|
||||
"useFileDialog": true,
|
||||
"useFileSystemAccess": true,
|
||||
"useFocus": true,
|
||||
"useFocusWithin": true,
|
||||
"useFps": true,
|
||||
"useFullscreen": true,
|
||||
"useGamepad": true,
|
||||
"useGeolocation": true,
|
||||
"useId": true,
|
||||
"useIdle": true,
|
||||
"useImage": true,
|
||||
"useInfiniteScroll": true,
|
||||
"useIntersectionObserver": true,
|
||||
"useInterval": true,
|
||||
"useIntervalFn": true,
|
||||
"useKeyModifier": true,
|
||||
"useLastChanged": true,
|
||||
"useLink": true,
|
||||
"useLocalStorage": true,
|
||||
"useMagicKeys": true,
|
||||
"useManualRefHistory": true,
|
||||
"useMediaControls": true,
|
||||
"useMediaQuery": true,
|
||||
"useMemoize": true,
|
||||
"useMemory": true,
|
||||
"useModel": true,
|
||||
"useMounted": true,
|
||||
"useMouse": true,
|
||||
"useMouseInElement": true,
|
||||
"useMousePressed": true,
|
||||
"useMutationObserver": true,
|
||||
"useNavigatorLanguage": true,
|
||||
"useNetwork": true,
|
||||
"useNow": true,
|
||||
"useObjectUrl": true,
|
||||
"useOffsetPagination": true,
|
||||
"useOnline": true,
|
||||
"usePageLeave": true,
|
||||
"useParallax": true,
|
||||
"useParentElement": true,
|
||||
"usePerformanceObserver": true,
|
||||
"usePermission": true,
|
||||
"usePointer": true,
|
||||
"usePointerLock": true,
|
||||
"usePointerSwipe": true,
|
||||
"usePreferredColorScheme": true,
|
||||
"usePreferredContrast": true,
|
||||
"usePreferredDark": true,
|
||||
"usePreferredLanguages": true,
|
||||
"usePreferredReducedMotion": true,
|
||||
"usePreferredReducedTransparency": true,
|
||||
"usePrevious": true,
|
||||
"useRafFn": true,
|
||||
"useRefHistory": true,
|
||||
"useResizeObserver": true,
|
||||
"useRoute": true,
|
||||
"useRouter": true,
|
||||
"useSSRWidth": true,
|
||||
"useScreenOrientation": true,
|
||||
"useScreenSafeArea": true,
|
||||
"useScriptTag": true,
|
||||
"useScroll": true,
|
||||
"useScrollLock": true,
|
||||
"useSessionStorage": true,
|
||||
"useShare": true,
|
||||
"useSlots": true,
|
||||
"useSorted": true,
|
||||
"useSpeechRecognition": true,
|
||||
"useSpeechSynthesis": true,
|
||||
"useStepper": true,
|
||||
"useStorage": true,
|
||||
"useStorageAsync": true,
|
||||
"useStyleTag": true,
|
||||
"useSupported": true,
|
||||
"useSwipe": true,
|
||||
"useTemplateRef": true,
|
||||
"useTemplateRefsList": true,
|
||||
"useTextDirection": true,
|
||||
"useTextSelection": true,
|
||||
"useTextareaAutosize": true,
|
||||
"useThrottle": true,
|
||||
"useThrottleFn": true,
|
||||
"useThrottledRefHistory": true,
|
||||
"useTimeAgo": true,
|
||||
"useTimeout": true,
|
||||
"useTimeoutFn": true,
|
||||
"useTimeoutPoll": true,
|
||||
"useTimestamp": true,
|
||||
"useTitle": true,
|
||||
"useToNumber": true,
|
||||
"useToString": true,
|
||||
"useToggle": true,
|
||||
"useTransition": true,
|
||||
"useUrlSearchParams": true,
|
||||
"useUserMedia": true,
|
||||
"useVModel": true,
|
||||
"useVModels": true,
|
||||
"useVibrate": true,
|
||||
"useVirtualList": true,
|
||||
"useWakeLock": true,
|
||||
"useWebNotification": true,
|
||||
"useWebSocket": true,
|
||||
"useWebWorker": true,
|
||||
"useWebWorkerFn": true,
|
||||
"useWindowFocus": true,
|
||||
"useWindowScroll": true,
|
||||
"useWindowSize": true,
|
||||
"watch": true,
|
||||
"watchArray": true,
|
||||
"watchAtMost": true,
|
||||
"watchDebounced": true,
|
||||
"watchDeep": true,
|
||||
"watchEffect": true,
|
||||
"watchIgnorable": true,
|
||||
"watchImmediate": true,
|
||||
"watchOnce": true,
|
||||
"watchPausable": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true,
|
||||
"watchThrottled": true,
|
||||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"whenever": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
@@ -0,0 +1,30 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
# frontend
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
|
||||
|
||||
## Type Support for `.vue` Imports in TS
|
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vite.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
pnpm build
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
pnpm lint
|
||||
```
|
||||
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -0,0 +1,25 @@
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
|
||||
import oxlint from 'eslint-plugin-oxlint'
|
||||
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
||||
|
||||
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
|
||||
// import { configureVueProject } from '@vue/eslint-config-typescript'
|
||||
// configureVueProject({ scriptLangs: ['ts', 'tsx'] })
|
||||
// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup
|
||||
|
||||
export default defineConfigWithVueTs(
|
||||
{
|
||||
name: 'app/files-to-lint',
|
||||
files: ['**/*.{ts,mts,tsx,vue}'],
|
||||
},
|
||||
|
||||
{
|
||||
name: 'app/files-to-ignore',
|
||||
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
|
||||
},
|
||||
pluginVue.configs['flat/essential'],
|
||||
vueTsConfigs.recommended,
|
||||
...oxlint.configs['flat/recommended'],
|
||||
skipFormatting,
|
||||
)
|
||||
@@ -0,0 +1,42 @@
|
||||
<!doctype html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="./favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Cache-control" content="no-cache" />
|
||||
<meta http-equiv="Cache" content="no-cache" />
|
||||
<meta name="baidu-site-verification" content="codeva-hGziQg28WN" />
|
||||
<title>DNF计算器</title>
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-J0NPDEYQJS"></script>
|
||||
<script>
|
||||
if (!window.pywebview) {
|
||||
// 百度统计
|
||||
// eslint-disable-next-line vars-on-top, no-var
|
||||
var _hmt = _hmt || []
|
||||
;(function () {
|
||||
const hm = document.createElement('script')
|
||||
hm.src = 'https://hm.baidu.com/hm.js?472775d2edd6fb31b00828eef60ba388'
|
||||
const s = document.querySelectorAll('script')[0]
|
||||
s.parentNode.insertBefore(hm, s)
|
||||
})()
|
||||
// Google 分析
|
||||
window.dataLayer = window.dataLayer || []
|
||||
function gtag(...args) {
|
||||
window.dataLayer.push(args)
|
||||
}
|
||||
gtag('js', new Date())
|
||||
gtag('config', 'G-J0NPDEYQJS')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- <script>
|
||||
window.flag
|
||||
= navigator.userAgent.match(/(phone|pad|pod|iphone|ipod|ios|ipad|android|mobile|blackberry|iemobile|mqqbrowser|juc|fennec|wosbrowser|browserng|webos|symbian|windows phone)/i)
|
||||
</script> -->
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check \"build-only {@}\" --",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build",
|
||||
"lint:oxlint": "oxlint . --fix -D correctness --ignore-path .gitignore",
|
||||
"lint:eslint": "eslint . --fix",
|
||||
"lint": "run-s lint:*",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/vue": "^4.3.0",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@vueuse/core": "^12.8.2",
|
||||
"axios": "^1.8.2",
|
||||
"pako": "^2.1.0",
|
||||
"pinia": "^3.0.1",
|
||||
"reka-ui": "^2.0.2",
|
||||
"sass": "^1.85.1",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node22": "^22.0.0",
|
||||
"@types/node": "^22.13.10",
|
||||
"@types/pako": "^2.0.3",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"@vue/eslint-config-typescript": "^14.5.0",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-plugin-oxlint": "^0.15.13",
|
||||
"eslint-plugin-vue": "~10.0.0",
|
||||
"jiti": "^2.4.2",
|
||||
"npm-run-all2": "^7.0.2",
|
||||
"oxlint": "^0.15.13",
|
||||
"prettier": "3.5.3",
|
||||
"typescript": "~5.8.0",
|
||||
"unocss": "66.1.0-beta.3",
|
||||
"unplugin-auto-import": "^19.1.1",
|
||||
"vite": "^6.2.1",
|
||||
"vite-plugin-vue-devtools": "^7.7.2",
|
||||
"vue-tsc": "^2.2.8"
|
||||
},
|
||||
"format": "prettier --write src/"
|
||||
}
|
||||
|
After Width: | Height: | Size: 264 KiB |
@@ -0,0 +1,119 @@
|
||||
import type { AxiosInstance, AxiosResponse } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { h } from 'vue'
|
||||
import { gzip, ungzip } from 'pako'
|
||||
// import { useAppStore, useConfigStore } from '@/store'
|
||||
// import { useDialog } from '@/components/hooks/dialog'
|
||||
|
||||
export interface HttpResponse<T = unknown> extends AxiosResponse {
|
||||
code?: number
|
||||
message: string
|
||||
data: T
|
||||
state?: number
|
||||
}
|
||||
|
||||
let instance: AxiosInstance | null = null
|
||||
|
||||
let baseURL = '/api'
|
||||
|
||||
// 避免远程开发的时候冲突
|
||||
if (process.env.NODE_ENV == 'development') {
|
||||
baseURL = 'http://127.0.0.1:17173/api'
|
||||
}
|
||||
|
||||
if (import.meta.env.MODE == 'web' || import.meta.env.MODE == 'show') {
|
||||
baseURL = 'https://api.dnftools.com/'
|
||||
}
|
||||
|
||||
// 解压
|
||||
function unzip(key: string) {
|
||||
// 将二进制字符串转换为字符数组
|
||||
|
||||
const charData = key.split('').map((x) => {
|
||||
return x?.charCodeAt(0)
|
||||
})
|
||||
|
||||
// 将数字数组转换成字节数组
|
||||
const binData = new Uint8Array(charData)
|
||||
|
||||
// 解压
|
||||
const data = ungzip(binData)
|
||||
|
||||
const decoder = new TextDecoder()
|
||||
const str = decoder.decode(data)
|
||||
|
||||
// unescape(str) --->解压后解码,防止中午乱码
|
||||
return str
|
||||
}
|
||||
|
||||
export function defineRequest<T>(fn: (ax: AxiosInstance) => T) {
|
||||
if (!instance) {
|
||||
instance = axios.create({
|
||||
baseURL,
|
||||
})
|
||||
|
||||
instance.interceptors.request.use(
|
||||
(request) => {
|
||||
// const configStore = useConfigStore()
|
||||
// const token = configStore.token
|
||||
// const uid = useAppStore().uid
|
||||
|
||||
const token = 'test'
|
||||
|
||||
if (token) {
|
||||
request.headers['Access-Token'] = token
|
||||
}
|
||||
|
||||
// 在网页端,会添加token
|
||||
const accessToken = localStorage.getItem('dcalc/access_token')
|
||||
|
||||
if (accessToken) {
|
||||
request.headers.Authorization = `Bearer ${accessToken}`
|
||||
}
|
||||
|
||||
return request
|
||||
},
|
||||
(error) => {
|
||||
// do something
|
||||
return Promise.reject(error)
|
||||
},
|
||||
)
|
||||
|
||||
instance.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
|
||||
// instance.defaults.headers["Accept-Encoding"] = "gzip"
|
||||
// instance.defaults.headers["Content-Encoding"] = "gzip"
|
||||
// add response interceptors
|
||||
instance.interceptors.response.use(
|
||||
async (response: AxiosResponse<HttpResponse>) => {
|
||||
if (response.data.code === 500) {
|
||||
// const { alert } = useDialog()
|
||||
// await alert({
|
||||
// content: () => {
|
||||
// return h(
|
||||
// 'div',
|
||||
// {
|
||||
// class: 'justify-center text-hex-d4d6b6 text-center',
|
||||
// style: 'white-space:pre-wrap;width:250px;margin:10px',
|
||||
// },
|
||||
// `出现错误,可加群反馈:183439472\n${response.data.message}`,
|
||||
// )
|
||||
// },
|
||||
// })
|
||||
}
|
||||
// 解密数据
|
||||
if (typeof response.data.data == 'string') {
|
||||
try {
|
||||
const data = unzip(atob(response.data.data as string))
|
||||
response.data.data = JSON.parse(data)
|
||||
} catch (e) {}
|
||||
}
|
||||
return response.data
|
||||
},
|
||||
async (error: Error) => {
|
||||
return Promise.reject(error)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return fn(Object.create(instance))
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import info from './info'
|
||||
|
||||
export default { ...info }
|
||||
@@ -0,0 +1,10 @@
|
||||
import { defineRequest } from '../common'
|
||||
import type { IAdventureInfo } from './type'
|
||||
|
||||
export default defineRequest((request) => {
|
||||
return {
|
||||
adventures() {
|
||||
return request.get<IAdventureInfo[]>('/adventure').then((res) => res.data)
|
||||
},
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
export interface IAdventureInfo {
|
||||
title: string
|
||||
name: string
|
||||
children: IAlterInfo[]
|
||||
}
|
||||
|
||||
export interface ITools {
|
||||
name: string
|
||||
tooltips: string
|
||||
link: string
|
||||
end?: Date
|
||||
target: '_blank' | '_self'
|
||||
}
|
||||
|
||||
export interface IMonster {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface IAlterOption {
|
||||
name: string
|
||||
title: string
|
||||
class?: string
|
||||
}
|
||||
|
||||
export interface IAlterInfo {
|
||||
name: string
|
||||
url?: string
|
||||
title: string
|
||||
default_value: string
|
||||
options?: IAlterOption[]
|
||||
open?: boolean
|
||||
comment?: string
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export interface IDataType<T = any> {
|
||||
code?: number
|
||||
message: string
|
||||
data: T
|
||||
state?: number
|
||||
}
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 928 B |
|
After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 322 B |
|
After Width: | Height: | Size: 355 B |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 711 B |
|
After Width: | Height: | Size: 617 B |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 595 B |
|
After Width: | Height: | Size: 22 KiB |