1.8
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""每日花园状态服务:连续天数 + 树渴了提醒"""
|
||||
|
||||
from datetime import date, datetime, timedelta
|
||||
|
||||
from sqlalchemy import select, or_
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.user_streak import UserStreak
|
||||
from app.models.friendship_tree import FriendshipTree
|
||||
from app.models.friend import Friend
|
||||
from app.models.user import User
|
||||
|
||||
|
||||
class DailyService:
|
||||
def __init__(self, db: AsyncSession):
|
||||
self.db = db
|
||||
|
||||
async def get_daily_status(self, user_id: str) -> dict:
|
||||
"""获取/更新今日花园状态"""
|
||||
today = date.today()
|
||||
result = await self.db.execute(
|
||||
select(UserStreak).where(UserStreak.user_id == user_id)
|
||||
)
|
||||
streak_row = result.scalars().first()
|
||||
|
||||
is_new_day_open = False
|
||||
if not streak_row:
|
||||
streak_row = UserStreak(
|
||||
user_id=user_id, streak=1, last_open_date=today, total_days=1,
|
||||
)
|
||||
self.db.add(streak_row)
|
||||
is_new_day_open = True
|
||||
elif streak_row.last_open_date != today:
|
||||
# 计算连续天数
|
||||
if streak_row.last_open_date == today - timedelta(days=1):
|
||||
streak_row.streak += 1 # 连续
|
||||
else:
|
||||
streak_row.streak = 1 # 断了,重新计数
|
||||
streak_row.last_open_date = today
|
||||
streak_row.total_days += 1
|
||||
is_new_day_open = True
|
||||
await self.db.flush()
|
||||
|
||||
# 找口渴的树(24 小时没浇水的)
|
||||
thirsty_trees = await self._get_thirsty_trees(user_id)
|
||||
|
||||
return {
|
||||
"streak": streak_row.streak,
|
||||
"total_days": streak_row.total_days,
|
||||
"is_new_day_open": is_new_day_open,
|
||||
"thirsty_count": len(thirsty_trees),
|
||||
"thirsty_trees": thirsty_trees[:3], # 最多提示 3 棵
|
||||
}
|
||||
|
||||
async def _get_thirsty_trees(self, user_id: str) -> list[dict]:
|
||||
"""获取口渴的好友之树(24h 未浇水)"""
|
||||
cutoff = datetime.utcnow() - timedelta(hours=24)
|
||||
# 查该用户参与的所有树
|
||||
result = await self.db.execute(
|
||||
select(FriendshipTree).where(
|
||||
or_(
|
||||
FriendshipTree.user_a_id == user_id,
|
||||
FriendshipTree.user_b_id == user_id,
|
||||
)
|
||||
)
|
||||
)
|
||||
thirsty = []
|
||||
for tree in result.scalars().all():
|
||||
if tree.last_watered_at is None or tree.last_watered_at < cutoff:
|
||||
friend_id = tree.user_b_id if tree.user_a_id == user_id else tree.user_a_id
|
||||
# 取好友信息
|
||||
fr = await self.db.execute(select(User).where(User.id == friend_id))
|
||||
friend = fr.scalars().first()
|
||||
if friend:
|
||||
thirsty.append({
|
||||
"friend_id": friend_id,
|
||||
"friend_name": friend.nickname or friend.username,
|
||||
"hours_since": int((datetime.utcnow() - (tree.last_watered_at or tree.created_at)).total_seconds() / 3600),
|
||||
})
|
||||
return thirsty
|
||||
Reference in New Issue
Block a user