更新 TETR.IO 模板 (#348)

*  更新路径以匹配模板

*  添加历史数据

* 🎨 优化模板模型代码结构

---------

Co-authored-by: shoucandanghehe <wallfjjd@gmail.com>
This commit is contained in:
渣渣120
2024-06-25 08:47:35 +08:00
committed by GitHub
parent 77b10a858e
commit 6291a2ba70
11 changed files with 100 additions and 108 deletions

View File

@@ -30,13 +30,13 @@ from ...utils.host import HostPage, get_self_netloc
from ...utils.metrics import TetrisMetricsProWithPPSVS, get_metrics
from ...utils.render import render
from ...utils.render.schemas.base import Avatar, Ranking
from ...utils.render.schemas.tetrio_info import Data, Radar, TetraLeague, TetraLeagueHistory
from ...utils.render.schemas.tetrio_info import Info as V1TemplateInfo
from ...utils.render.schemas.tetrio_info import User as V1TemplateUser
from ...utils.render.schemas.tetrio_info_v2 import Badge, Blitz, Sprint, Statistic, TetraLeagueStatistic
from ...utils.render.schemas.tetrio_info_v2 import Info as V2TemplateInfo
from ...utils.render.schemas.tetrio_info_v2 import TetraLeague as V2TemplateTetraLeague
from ...utils.render.schemas.tetrio_info_v2 import User as V2TemplateUser
from ...utils.render.schemas.tetrio.tetrio_info import Info as V1TemplateInfo
from ...utils.render.schemas.tetrio.tetrio_info import Radar, TetraLeague, TetraLeagueHistory, TetraLeagueHistoryData
from ...utils.render.schemas.tetrio.tetrio_info import User as V1TemplateUser
from ...utils.render.schemas.tetrio.tetrio_user_info_v2 import Badge, Blitz, Sprint, Statistic, TetraLeagueStatistic
from ...utils.render.schemas.tetrio.tetrio_user_info_v2 import Info as V2TemplateInfo
from ...utils.render.schemas.tetrio.tetrio_user_info_v2 import TetraLeague as V2TemplateTetraLeague
from ...utils.render.schemas.tetrio.tetrio_user_info_v2 import User as V2TemplateUser
from ...utils.screenshot import screenshot
from ...utils.typing import Me, Number
from ..constant import CANT_VERIFY_MESSAGE
@@ -129,10 +129,10 @@ def get_split(value_max: int, value_min: int) -> tuple[int, int]:
def get_specified_point(
previous_point: Data,
behind_point: Data,
previous_point: TetraLeagueHistoryData,
behind_point: TetraLeagueHistoryData,
point_time: datetime,
) -> Data:
) -> TetraLeagueHistoryData:
"""根据给出的 previous_point 和 behind_point, 推算 point_time 点处的数据
Args:
@@ -147,13 +147,13 @@ def get_specified_point(
slope = (behind_point.tr - previous_point.tr) / (
datetime.timestamp(behind_point.record_at) - datetime.timestamp(previous_point.record_at)
)
return Data(
return TetraLeagueHistoryData(
record_at=point_time,
tr=previous_point.tr + slope * (datetime.timestamp(point_time) - datetime.timestamp(previous_point.record_at)),
)
async def query_historical_data(user: User, user_info: UserInfoSuccess) -> list[Data]:
async def query_historical_data(user: User, user_info: UserInfoSuccess) -> list[TetraLeagueHistoryData]:
today = datetime.now(ZoneInfo('Asia/Shanghai')).replace(hour=0, minute=0, second=0, microsecond=0)
forward = timedelta(days=9)
start_time = (today - forward).astimezone(UTC)
@@ -183,11 +183,11 @@ async def query_historical_data(user: User, user_info: UserInfoSuccess) -> list[
full_export_data = FullExport.get_data(user.unique_identifier)
if not historical_data and not full_export_data:
return [
Data(record_at=today - forward, tr=user_info.data.user.league.rating),
Data(record_at=today.replace(microsecond=1000), tr=user_info.data.user.league.rating),
TetraLeagueHistoryData(record_at=today - forward, tr=user_info.data.user.league.rating),
TetraLeagueHistoryData(record_at=today.replace(microsecond=1000), tr=user_info.data.user.league.rating),
]
histories = [
Data(
TetraLeagueHistoryData(
record_at=i.update_time.astimezone(ZoneInfo('Asia/Shanghai')),
tr=i.data.data.user.league.rating,
)
@@ -208,7 +208,7 @@ async def query_historical_data(user: User, user_info: UserInfoSuccess) -> list[
histories.append(
get_specified_point(
histories[-1],
Data(record_at=user_info.cache.cached_at, tr=user_info.data.user.league.rating),
TetraLeagueHistoryData(record_at=user_info.cache.cached_at, tr=user_info.data.user.league.rating),
today.replace(microsecond=1000),
)
)
@@ -219,7 +219,7 @@ async def query_historical_data(user: User, user_info: UserInfoSuccess) -> list[
today - forward,
)
else:
histories.insert(0, Data(record_at=today - forward, tr=histories[0].tr))
histories.insert(0, TetraLeagueHistoryData(record_at=today - forward, tr=histories[0].tr))
return histories
@@ -322,6 +322,7 @@ async def make_query_image_v2(player: Player) -> bytes:
player.user, player.get_info(), player.sprint, player.blitz, player.zen
)
league = get_league(user_info)
histories = await query_historical_data(user, user_info)
if sprint.record is not None:
duration = timedelta(milliseconds=sprint.record.endcontext.final_time).total_seconds()
@@ -342,7 +343,7 @@ async def make_query_image_v2(player: Player) -> bytes:
netloc = get_self_netloc()
async with HostPage(
await render(
'v2/tetrio/info',
'v2/tetrio/user/info',
V2TemplateInfo(
user=V2TemplateUser(
id=user.ID,
@@ -397,6 +398,7 @@ async def make_query_image_v2(player: Player) -> bytes:
wins=league.gameswon,
),
decaying=league.decaying,
history=histories,
)
if isinstance(league, RatedLeague)
else None,
@@ -510,8 +512,8 @@ class FullExport:
cls.latest_update = datetime.now(tz=ZoneInfo('Asia/Shanghai')).date()
@classmethod
def get_data(cls, unique_identifier: str) -> list[Data]:
return [Data(record_at=i[0], tr=i[1]) for i in cls.cache[unique_identifier]]
def get_data(cls, unique_identifier: str) -> list[TetraLeagueHistoryData]:
return [TetraLeagueHistoryData(record_at=i[0], tr=i[1]) for i in cls.cache[unique_identifier]]
@classmethod
def start_time(cls) -> datetime:

View File

@@ -17,8 +17,8 @@ from ....utils.host import HostPage, get_self_netloc
from ....utils.metrics import get_metrics
from ....utils.render import render
from ....utils.render.schemas.base import Avatar
from ....utils.render.schemas.tetrio_record_base import Finesse, Max, Mini, Tspins, User
from ....utils.render.schemas.tetrio_record_blitz import Record, Statistic
from ....utils.render.schemas.tetrio.tetrio_record_base import Finesse, Max, Mini, Tspins, User
from ....utils.render.schemas.tetrio.tetrio_record_blitz import Record, Statistic
from ....utils.screenshot import screenshot
from ....utils.typing import Me
from ...constant import CANT_VERIFY_MESSAGE

View File

@@ -17,8 +17,8 @@ from ....utils.host import HostPage, get_self_netloc
from ....utils.metrics import get_metrics
from ....utils.render import render
from ....utils.render.schemas.base import Avatar
from ....utils.render.schemas.tetrio_record_base import Finesse, Max, Mini, Tspins, User
from ....utils.render.schemas.tetrio_record_sprint import Record, Statistic
from ....utils.render.schemas.tetrio.tetrio_record_base import Finesse, Max, Mini, Tspins, User
from ....utils.render.schemas.tetrio.tetrio_record_sprint import Record, Statistic
from ....utils.screenshot import screenshot
from ....utils.typing import Me
from ...constant import CANT_VERIFY_MESSAGE

View File

@@ -5,10 +5,10 @@ from nonebot.compat import PYDANTIC_V2
from ..templates import templates_dir
from .schemas.bind import Bind
from .schemas.tetrio_info import Info as TETRIOInfo
from .schemas.tetrio_info_v2 import Info as TETRIOInfoV2
from .schemas.tetrio_record_blitz import Record as TETRIORecordBlitz
from .schemas.tetrio_record_sprint import Record as TETRIORecordSprint
from .schemas.tetrio.tetrio_info import Info as TETRIOInfo
from .schemas.tetrio.tetrio_record_blitz import Record as TETRIORecordBlitz
from .schemas.tetrio.tetrio_record_sprint import Record as TETRIORecordSprint
from .schemas.tetrio.tetrio_user_info_v2 import Info as TETRIOUserInfoV2
from .schemas.top_info import Info as TOPInfo
from .schemas.tos_info import Info as TOSInfo
@@ -34,7 +34,7 @@ async def render(render_type: Literal['v1/tos/info'], data: TOSInfo) -> str: ...
@overload
async def render(render_type: Literal['v2/tetrio/info'], data: TETRIOInfoV2) -> str: ...
async def render(render_type: Literal['v2/tetrio/user/info'], data: TETRIOUserInfoV2) -> str: ...
@overload
@@ -51,11 +51,11 @@ async def render(
'v1/tetrio/info',
'v1/top/info',
'v1/tos/info',
'v2/tetrio/info',
'v2/tetrio/user/info',
'v2/tetrio/record/40l',
'v2/tetrio/record/blitz',
],
data: Bind | TETRIOInfo | TOPInfo | TOSInfo | TETRIOInfoV2 | TETRIORecordSprint | TETRIORecordBlitz,
data: Bind | TETRIOInfo | TOPInfo | TOSInfo | TETRIOUserInfoV2 | TETRIORecordSprint | TETRIORecordBlitz,
) -> str:
if PYDANTIC_V2:
return await env.get_template('index.html').render_async(

View File

@@ -0,0 +1,10 @@
from datetime import datetime
from pydantic import BaseModel
from ....typing import Number
class TetraLeagueHistoryData(BaseModel):
record_at: datetime
tr: Number

View File

@@ -0,0 +1,49 @@
from pydantic import BaseModel
from .....games.tetrio.api.typing import Rank
from ....typing import Number
from ..base import People, Ranking
from .base import TetraLeagueHistoryData
class User(People):
bio: str | None
class TetraLeague(BaseModel):
rank: Rank
tr: Number
global_rank: Number
pps: Number
lpm: Number
apm: Number
apl: Number
vs: Number
adpm: Number
adpl: Number
class TetraLeagueHistory(BaseModel):
data: list[TetraLeagueHistoryData]
split_interval: Number
min_tr: Number
max_tr: Number
offset: Number
class Radar(BaseModel):
app: Number
dsps: Number
dspp: Number
ci: Number
ge: Number
class Info(BaseModel):
user: User
ranking: Ranking
tetra_league: TetraLeague
tetra_league_history: TetraLeagueHistory
radar: Radar
sprint: str
blitz: str

View File

@@ -1,6 +1,6 @@
from pydantic import BaseModel
from .base import People
from ..base import People
class User(People):

View File

@@ -2,10 +2,11 @@ from datetime import datetime
from pydantic import BaseModel
from ....games.tetrio.api.schemas.user_records import Zen
from ....games.tetrio.api.typing import Rank
from ...typing import Number
from .base import Avatar
from .....games.tetrio.api.schemas.user_records import Zen
from .....games.tetrio.api.typing import Rank
from ....typing import Number
from ..base import Avatar
from .base import TetraLeagueHistoryData
class Badge(BaseModel):
@@ -72,6 +73,8 @@ class TetraLeague(BaseModel):
decaying: bool
history: list[TetraLeagueHistoryData]
class Sprint(BaseModel):
time: str

View File

@@ -1,72 +0,0 @@
from datetime import datetime
from typing import Annotated, ClassVar
from nonebot.compat import PYDANTIC_V2
from pydantic import BaseModel
from ....games.tetrio.api.typing import Rank
from ...typing import Number
from .base import People, Ranking
if PYDANTIC_V2:
from pydantic import PlainSerializer
def format_datetime_to_timestamp(dt: datetime) -> int:
return int(dt.timestamp() * 1000)
class User(People):
bio: str | None
class TetraLeague(BaseModel):
rank: Rank
tr: Number
global_rank: Number
pps: Number
lpm: Number
apm: Number
apl: Number
vs: Number
adpm: Number
adpl: Number
class Data(BaseModel):
if PYDANTIC_V2:
record_at: Annotated[datetime, PlainSerializer(format_datetime_to_timestamp, return_type=int)]
else:
record_at: datetime # type: ignore[no-redef]
tr: Number
class TetraLeagueHistory(BaseModel):
data: list[Data]
split_interval: Number
min_tr: Number
max_tr: Number
offset: Number
class Radar(BaseModel):
app: Number
dsps: Number
dspp: Number
ci: Number
ge: Number
class Info(BaseModel):
user: User
ranking: Ranking
tetra_league: TetraLeague
tetra_league_history: TetraLeagueHistory
radar: Radar
sprint: str
blitz: str
if not PYDANTIC_V2:
class Config:
json_encoders: ClassVar[dict] = {datetime: format_datetime_to_timestamp}