From 52a6d95434e9ff4b1ad6b968e2dfc91eee800a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=B5=E5=91=B5=E3=81=A7=E3=81=99?= <51957264+shoucandanghehe@users.noreply.github.com> Date: Sat, 19 Jul 2025 22:40:04 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=E7=A7=BB=E9=99=A4=20julianday?= =?UTF-8?q?=20=E7=9A=84=E4=BD=BF=E7=94=A8=EF=BC=8C=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=9B=B4=E5=A4=9A=E6=95=B0=E6=8D=AE=E5=BA=93=20(#550)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../games/tetrio/rank/all.py | 44 ++++++++++++++----- .../games/tetrio/rank/detail.py | 43 +++++++++++++----- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/nonebot_plugin_tetris_stats/games/tetrio/rank/all.py b/nonebot_plugin_tetris_stats/games/tetrio/rank/all.py index 6900675..47d35c0 100644 --- a/nonebot_plugin_tetris_stats/games/tetrio/rank/all.py +++ b/nonebot_plugin_tetris_stats/games/tetrio/rank/all.py @@ -5,7 +5,7 @@ from nonebot_plugin_alconna import Option, Subcommand, UniMessage from nonebot_plugin_orm import get_session from nonebot_plugin_uninfo import Uninfo from nonebot_plugin_uninfo.orm import get_session_persist_id -from sqlalchemy import func, select +from sqlalchemy import select from sqlalchemy.orm import selectinload from ....db import trigger @@ -41,6 +41,7 @@ async def _(event_session: Uninfo, template: Template | None = None): command_args=['--all'] + ([f'--template {template}'] if template is not None else []), ): async with get_session() as session: + # 获取最新记录 latest_data = ( await session.scalars( select(TETRIOLeagueStats) @@ -49,19 +50,42 @@ async def _(event_session: Uninfo, template: Template | None = None): .options(selectinload(TETRIOLeagueStats.fields)) ) ).one() - compare_data = ( - await session.scalars( + + # 计算目标时间点 (24小时前) + target_time = latest_data.update_time - timedelta(hours=24) + + # 查询目标时间点之前的最近记录 + before = ( + await session.scalar( select(TETRIOLeagueStats) - .order_by( - func.abs( - func.julianday(TETRIOLeagueStats.update_time) - - func.julianday(latest_data.update_time - timedelta(hours=24)) - ) - ) + .where(TETRIOLeagueStats.update_time <= target_time) + .order_by(TETRIOLeagueStats.update_time.desc()) .limit(1) .options(selectinload(TETRIOLeagueStats.fields)) ) - ).one() + or latest_data + ) + + # 查询目标时间点之后的最近记录 + after = ( + await session.scalar( + select(TETRIOLeagueStats) + .where(TETRIOLeagueStats.update_time >= target_time) # 使用 >= 避免间隙 + .order_by(TETRIOLeagueStats.update_time.asc()) + .limit(1) + .options(selectinload(TETRIOLeagueStats.fields)) + ) + or latest_data + ) + + # 确定最接近的记录 + compare_data = ( + before + if abs((target_time - before.update_time).total_seconds()) + < abs((target_time - after.update_time).total_seconds()) + else after + ) + match template: case 'v1' | None: await UniMessage.image(raw=await make_image_v1(latest_data, compare_data)).finish() diff --git a/nonebot_plugin_tetris_stats/games/tetrio/rank/detail.py b/nonebot_plugin_tetris_stats/games/tetrio/rank/detail.py index 4deef28..eefd0aa 100644 --- a/nonebot_plugin_tetris_stats/games/tetrio/rank/detail.py +++ b/nonebot_plugin_tetris_stats/games/tetrio/rank/detail.py @@ -7,7 +7,7 @@ from nonebot_plugin_alconna import Option, UniMessage from nonebot_plugin_orm import get_session from nonebot_plugin_uninfo import Uninfo from nonebot_plugin_uninfo.orm import get_session_persist_id -from sqlalchemy import func, select +from sqlalchemy import select from sqlalchemy.orm import selectinload from ....db import trigger @@ -39,6 +39,7 @@ async def _(rank: ValidRank, event_session: Uninfo): command_args=[f'--detail {rank}'], ): async with get_session() as session: + # 获取最新记录 latest_data = ( await session.scalars( select(TETRIOLeagueStats) @@ -47,19 +48,41 @@ async def _(rank: ValidRank, event_session: Uninfo): .options(selectinload(TETRIOLeagueStats.fields)) ) ).one() - compare_data = ( - await session.scalars( + + # 计算目标时间点 (24小时前) + target_time = latest_data.update_time - timedelta(hours=24) + + # 查询目标时间点之前的最近记录 + before = ( + await session.scalar( select(TETRIOLeagueStats) - .order_by( - func.abs( - func.julianday(TETRIOLeagueStats.update_time) - - func.julianday(latest_data.update_time - timedelta(hours=24)) - ) - ) + .where(TETRIOLeagueStats.update_time <= target_time) + .order_by(TETRIOLeagueStats.update_time.desc()) .limit(1) .options(selectinload(TETRIOLeagueStats.fields)) ) - ).one() + or latest_data # 回退到最新记录 + ) + + # 查询目标时间点之后的最近记录 + after = ( + await session.scalar( + select(TETRIOLeagueStats) + .where(TETRIOLeagueStats.update_time >= target_time) + .order_by(TETRIOLeagueStats.update_time.asc()) + .limit(1) + .options(selectinload(TETRIOLeagueStats.fields)) + ) + or latest_data # 回退到最新记录 + ) + + # 确定最接近的记录 + compare_data = ( + before + if abs((target_time - before.update_time).total_seconds()) + < abs((target_time - after.update_time).total_seconds()) + else after + ) await UniMessage.image( raw=await make_image( rank,