98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
"""内驱力数据访问(好奇问题 + 探索性次生目标)。"""
|
|
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models.drive import CuriosityQuestion, ExploratorySubgoal
|
|
|
|
|
|
async def add_curiosities(session: AsyncSession, curiosities: list[CuriosityQuestion]) -> None:
|
|
session.add_all(curiosities)
|
|
await session.flush()
|
|
|
|
|
|
async def get_curiosity(session: AsyncSession, curiosity_id: str) -> CuriosityQuestion | None:
|
|
return await session.get(CuriosityQuestion, curiosity_id)
|
|
|
|
|
|
async def list_curiosities(
|
|
session: AsyncSession,
|
|
character_id: str,
|
|
*,
|
|
source: str | None = None,
|
|
page: int = 1,
|
|
page_size: int = 20,
|
|
) -> tuple[list[CuriosityQuestion], int]:
|
|
conditions = [CuriosityQuestion.character_id == character_id]
|
|
if source is not None:
|
|
conditions.append(CuriosityQuestion.source == source)
|
|
total = (
|
|
await session.execute(
|
|
select(func.count()).select_from(CuriosityQuestion).where(*conditions)
|
|
)
|
|
).scalar_one()
|
|
items = await session.execute(
|
|
select(CuriosityQuestion)
|
|
.where(*conditions)
|
|
.order_by(CuriosityQuestion.created_at.desc())
|
|
.offset(max(page - 1, 0) * page_size)
|
|
.limit(page_size)
|
|
)
|
|
return list(items.scalars().all()), int(total or 0)
|
|
|
|
|
|
async def add_subgoals(session: AsyncSession, subgoals: list[ExploratorySubgoal]) -> None:
|
|
session.add_all(subgoals)
|
|
await session.flush()
|
|
|
|
|
|
async def get_subgoal(session: AsyncSession, subgoal_id: str) -> ExploratorySubgoal | None:
|
|
return await session.get(ExploratorySubgoal, subgoal_id)
|
|
|
|
|
|
async def list_subgoals(
|
|
session: AsyncSession,
|
|
character_id: str,
|
|
*,
|
|
status: str | None = None,
|
|
page: int = 1,
|
|
page_size: int = 20,
|
|
) -> tuple[list[ExploratorySubgoal], int]:
|
|
conditions = [ExploratorySubgoal.character_id == character_id]
|
|
if status is not None:
|
|
conditions.append(ExploratorySubgoal.status == status)
|
|
total = (
|
|
await session.execute(
|
|
select(func.count()).select_from(ExploratorySubgoal).where(*conditions)
|
|
)
|
|
).scalar_one()
|
|
items = await session.execute(
|
|
select(ExploratorySubgoal)
|
|
.where(*conditions)
|
|
.order_by(ExploratorySubgoal.created_at.desc())
|
|
.offset(max(page - 1, 0) * page_size)
|
|
.limit(page_size)
|
|
)
|
|
return list(items.scalars().all()), int(total or 0)
|
|
|
|
|
|
async def list_approved_subgoals(
|
|
session: AsyncSession,
|
|
character_id: str,
|
|
limit: int = 5,
|
|
) -> list[ExploratorySubgoal]:
|
|
"""列出已批准(approved)的次生目标,按 created_at 升序排列。
|
|
|
|
供大周天自主探索执行阶段拾取。
|
|
"""
|
|
result = await session.execute(
|
|
select(ExploratorySubgoal)
|
|
.where(
|
|
ExploratorySubgoal.character_id == character_id,
|
|
ExploratorySubgoal.status == "approved",
|
|
)
|
|
.order_by(ExploratorySubgoal.created_at.asc())
|
|
.limit(limit)
|
|
)
|
|
return list(result.scalars().all())
|