feat(遊戲化): 新增大廳、附身、時間流、後日談進度等遊戲化系統功能
新增角色大廳(lobby)邀約與通話、附身(possession)、時鐘(clock)抽象、 時間流與睡眠負債、後日談進度、行為選擇與旁觀反應等模組,並補齊對應冒煙 測試(R~V)與單元測試;同步調整 web/mobile 對應頁面與元件。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+12
-10
@@ -72,16 +72,18 @@ export default async function smokeI() {
|
||||
}
|
||||
|
||||
// I-4 破例規則:睡眠時段一般不回應,且不應無條件破例
|
||||
const sleepSessionA = "smoke-i-sleep-a-" + Date.now();
|
||||
const noExceptionResult = await post(`/chat/${CHARACTER_ID}`, {
|
||||
// T38:每個獨立情境各自用一間 SOLO 房並在檢查完後結束,對應舊版「各自獨立 sessionId」的語意
|
||||
// (避免工作記憶互相污染;房間結束後下一個情境會取得全新的房間)。
|
||||
const sleepRoomA = await post("/room/solo", { userId: USER_ID, characterId: CHARACTER_ID });
|
||||
const noExceptionResult = await post(`/room/${sleepRoomA.id}/message`, {
|
||||
userId: USER_ID,
|
||||
sessionId: sleepSessionA,
|
||||
text: "在嗎",
|
||||
now: WEEKDAY_SLEEP_TIME,
|
||||
});
|
||||
if (noExceptionResult.text !== "" || noExceptionResult.availability !== "NO_REPLY") {
|
||||
throw new Error("條件不足時睡眠時段不應破例回應");
|
||||
}
|
||||
await post(`/room/${sleepRoomA.id}/end`, {});
|
||||
|
||||
// 條件滿足(親密度高+使用者情緒低落)時應觸發「深夜還陪你聊」破例
|
||||
await prisma.relationship.update({
|
||||
@@ -92,22 +94,21 @@ export default async function smokeI() {
|
||||
where: { characterId: CHARACTER_ID },
|
||||
data: { calm: 100, joy: 0, sad: 0, alert: 0, shy: 0, grumpy: 0, updatedAt: new Date(WEEKDAY_SLEEP_TIME) },
|
||||
});
|
||||
const sleepSessionB = "smoke-i-sleep-b-" + Date.now();
|
||||
const exceptionResult = await post(`/chat/${CHARACTER_ID}`, {
|
||||
const sleepRoomB = await post("/room/solo", { userId: USER_ID, characterId: CHARACTER_ID });
|
||||
const exceptionResult = await post(`/room/${sleepRoomB.id}/message`, {
|
||||
userId: USER_ID,
|
||||
sessionId: sleepSessionB,
|
||||
text: "我今天過得好難過,很失望",
|
||||
now: WEEKDAY_SLEEP_TIME,
|
||||
});
|
||||
if (exceptionResult.exceptionType !== "LATE_NIGHT_CHAT" || !exceptionResult.text) {
|
||||
throw new Error("條件滿足時應觸發「深夜還陪你聊」破例並正常生成回應");
|
||||
}
|
||||
await post(`/room/${sleepRoomB.id}/end`, {});
|
||||
|
||||
// 冷卻期內同類破例不應再次觸發
|
||||
const sleepSessionC = "smoke-i-sleep-c-" + Date.now();
|
||||
const cooldownResult = await post(`/chat/${CHARACTER_ID}`, {
|
||||
const sleepRoomC = await post("/room/solo", { userId: USER_ID, characterId: CHARACTER_ID });
|
||||
const cooldownResult = await post(`/room/${sleepRoomC.id}/message`, {
|
||||
userId: USER_ID,
|
||||
sessionId: sleepSessionC,
|
||||
text: "我今天過得好難過,很失望",
|
||||
now: WEEKDAY_SLEEP_TIME,
|
||||
});
|
||||
@@ -157,6 +158,7 @@ export default async function smokeI() {
|
||||
throw new Error("同一天不應重複生成離線事件");
|
||||
}
|
||||
|
||||
// 清理本次測試建立的角色(cascade 會一併清掉作息表、破例紀錄、記憶等)
|
||||
// 清理本次測試建立的角色(cascade 會一併清掉作息表、破例紀錄、記憶等)與本次建立的三間 SOLO 房。
|
||||
await prisma.room.deleteMany({ where: { id: { in: [sleepRoomA.id, sleepRoomB.id, sleepRoomC.id] } } });
|
||||
await prisma.character.deleteMany({ where: { id: CHARACTER_ID } });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user