// stores/games/turtlesoup.ts import { defineStore } from 'pinia' import { turtleSoupService } from '@/services/games/turtlesoup' import { type TurtleSoupGameHostView, type TurtleSoupGamePlayerView, type TurtleSoupQuestion, type TurtleSoupHint, type TurtleSoupTheme, type TurtleSoupPuzzle, type TurtleSoupGameSettings, TurtleSoupAnswerType, TurtleSoupGameStatus, TurtleSoupDifficulty } from '@/types/games/turtlesoup' import { useUserStore } from '@/stores/user' import { RoomStatus } from '@/types/room' import { ref, computed } from 'vue' export const useTurtleSoupStore = defineStore('turtlesoup', () => { // 基本状态 const hostView = ref(null) const playerView = ref(null) const loading = ref(false) const submitting = ref(false) const error = ref(null) const isHost = ref(false) const localDraft = ref('') // 问题/解答草稿 // 游戏设置 - 主持人创建或修改游戏时使用 const gameSettings = ref({ themeId: '', puzzleId: '', difficulty: TurtleSoupDifficulty.MEDIUM, maxPlayers: 10, isPrivate: false }) // 可用主题列表 const availableThemes = ref([]) // 可用题目列表 const availablePuzzles = ref([]) // 计算属性 const currentView = computed(() => { return isHost.value ? hostView.value : playerView.value }) // 获取游戏状态 const gameStatus = computed(() => { return currentView.value?.status || TurtleSoupGameStatus.CREATED }) // 游戏是否激活 const isGameActive = computed(() => { return gameStatus.value === TurtleSoupGameStatus.ACTIVE }) // 获取已公开的提示 const revealedHints = computed(() => { if (isHost.value && hostView.value) { return hostView.value.hints.filter(hint => hint.revealed) } else if (playerView.value) { return playerView.value.revealedHints } return [] }) // 获取未公开的提示 (只有主持人可见) const unrevealedHints = computed(() => { if (isHost.value && hostView.value) { return hostView.value.hints.filter(hint => !hint.revealed) } return [] }) // 获取排序后的问题列表(最新的在前) const sortedQuestions = computed(() => { if (isHost.value && hostView.value) { return [...hostView.value.questions].sort((a, b) => b.timestamp - a.timestamp) } else if (playerView.value) { return [...playerView.value.allQuestions].sort((a, b) => b.timestamp - a.timestamp) } return [] }) // 获取待回答的问题(只有主持人可见) const pendingQuestions = computed(() => { if (isHost.value && hostView.value) { return hostView.value.questions.filter(q => !q.answered) .sort((a, b) => b.timestamp - a.timestamp) } return [] }) // 获取我的问题(玩家视图) const myQuestions = computed(() => { if (!isHost.value && playerView.value) { return playerView.value.myQuestions.sort((a, b) => b.timestamp - a.timestamp) } return [] }) // 获取游戏时长(分钟) const gameDuration = computed(() => { const view = currentView.value if (!view || !view.startTime) return 0 return Math.floor(((view.currentTime || Date.now()) - view.startTime) / 60000) }) // 获取游戏进度 const gameProgress = computed(() => { return currentView.value?.progress || 0 }) // 获取房间代码 const roomCode = computed(() => { return isHost.value && hostView.value ? hostView.value.roomCode : '' }) // 游戏是否已结束 const isGameEnded = computed(() => { return gameStatus.value === TurtleSoupGameStatus.COMPLETED || gameStatus.value === TurtleSoupGameStatus.ABANDONED }) // Actions // 重置状态 function resetState() { hostView.value = null playerView.value = null loading.value = false submitting.value = false error.value = null isHost.value = false localDraft.value = '' // 重置游戏设置到默认值 gameSettings.value = { themeId: '', puzzleId: '', difficulty: TurtleSoupDifficulty.MEDIUM, maxPlayers: 10, isPrivate: false } } // 设置游戏视图类型 function setViewType(role: 'host' | 'player') { isHost.value = role === 'host' } // 更新游戏设置 function updateGameSettings(settings: Partial) { gameSettings.value = { ...gameSettings.value, ...settings } } // 加载可用的主题列表 async function loadThemes() { if (availableThemes.value.length > 0) return availableThemes.value loading.value = true error.value = null try { const result = await turtleSoupService.getThemes() if (result.success && result.data) { availableThemes.value = result.data return result.data } else { error.value = result.message || '加载主题失败' return [] } } catch (e) { console.error('加载主题失败:', e) error.value = e instanceof Error ? e.message : '未知错误' return [] } finally { loading.value = false } } async function unlockTheme(themeId: string) { const result = await turtleSoupService.unlockTheme(themeId) if (result.success) { return result } return null } // 加载可用的题目列表 async function loadPuzzles(themeId: string, difficulty?: TurtleSoupDifficulty) { loading.value = true error.value = null try { const result = await turtleSoupService.getPuzzles(themeId, difficulty) if (result.success && result.data) { availablePuzzles.value = result.data return result.data } else { error.value = result.message || '加载题目失败' return [] } } catch (e) { console.error('加载题目失败:', e) error.value = e instanceof Error ? e.message : '未知错误' return [] } finally { loading.value = false } } // 加载主持人游戏视图 async function loadHostGame(gameId: string) { loading.value = true error.value = null isHost.value = true try { const result = await turtleSoupService.getHostGameData(gameId) if (result.success && result.data) { hostView.value = result.data return true } else { error.value = result.message || '加载游戏数据失败' return false } } catch (e) { console.error('加载主持人游戏视图失败:', e) error.value = e instanceof Error ? e.message : '未知错误' return false } finally { loading.value = false } } // 加载玩家游戏视图 async function loadPlayerGame(gameId: string) { loading.value = true error.value = null isHost.value = false try { const result = await turtleSoupService.getPlayerGameData(gameId) if (result.success && result.data) { playerView.value = result.data return true } else { error.value = result.message || '加载游戏数据失败' return false } } catch (e) { console.error('加载玩家游戏视图失败:', e) error.value = e instanceof Error ? e.message : '未知错误' return false } finally { loading.value = false } } // 转换游戏状态为房间状态 function gameStatusToRoomStatus(status: TurtleSoupGameStatus): RoomStatus { switch (status) { case TurtleSoupGameStatus.CREATED: case TurtleSoupGameStatus.WAITING: return RoomStatus.WAITING case TurtleSoupGameStatus.ACTIVE: return RoomStatus.PLAYING case TurtleSoupGameStatus.COMPLETED: case TurtleSoupGameStatus.ABANDONED: return RoomStatus.ENDED default: return RoomStatus.WAITING } } // 创建新游戏 - 只处理游戏部分的数据 async function createGame(settings: TurtleSoupGameSettings) { submitting.value = true error.value = null try { // 保存游戏设置 gameSettings.value = settings // 创建游戏 const result = await turtleSoupService.createGame(settings) if (result.success && result.data) { return { success: true, gameId: result.data.gameId, roomId: result.data.roomId } } else { error.value = result.message || '创建游戏失败' return { success: false, message: error.value } } } catch (e) { console.error('创建游戏失败:', e) error.value = e instanceof Error ? e.message : '创建游戏时发生错误' return { success: false, message: error.value } } finally { submitting.value = false } } // 开始游戏 async function startGame() { if (!isHost.value || !hostView.value) { error.value = '主持人视图未加载' return false } submitting.value = true error.value = null try { const result = await turtleSoupService.startGame(hostView.value.id) if (result.success) { // 更新游戏状态 if (hostView.value) { hostView.value = { ...hostView.value, status: TurtleSoupGameStatus.ACTIVE, startTime: Date.now(), currentTime: Date.now() } } return true } else { error.value = result.message || '开始游戏失败' return false } } catch (e) { console.error('开始游戏失败:', e) error.value = e instanceof Error ? e.message : '开始游戏时发生错误' return false } finally { submitting.value = false } } // 提交问题 (玩家) async function submitQuestion(content: string) { if (!playerView.value || !content.trim()) { error.value = '无效的问题或游戏未加载' return false } submitting.value = true error.value = null try { const userStore = useUserStore() const result = await turtleSoupService.submitQuestion(playerView.value.id, content) if (result.success && result.data) { // 创建新问题对象 const newQuestion: TurtleSoupQuestion = { id: result.data.questionId, content, askedBy: userStore.openid, askedByName: userStore.nickname, timestamp: Date.now(), answered: false } // 更新本地玩家视图 if (playerView.value) { playerView.value = { ...playerView.value, myQuestions: [...playerView.value.myQuestions, newQuestion] } } // 清空草稿 localDraft.value = '' return true } else { error.value = result.message || '提交问题失败' return false } } catch (e) { console.error('提交问题失败:', e) error.value = e instanceof Error ? e.message : '提交问题时发生错误' return false } finally { submitting.value = false } } // 回答问题 (主持人) async function answerQuestion(questionId: string, answer: TurtleSoupAnswerType) { if (!isHost.value || !hostView.value) { error.value = '主持人视图未加载' return false } submitting.value = true error.value = null try { const result = await turtleSoupService.answerQuestion(questionId, answer) if (result.success) { // 更新本地状态 if (hostView.value) { const updatedQuestions = hostView.value.questions.map(q => { if (q.id === questionId) { return { ...q, answer, answered: true, answeredAt: Date.now() } } return q }) hostView.value = { ...hostView.value, questions: updatedQuestions } } return true } else { error.value = result.message || '回答问题失败' return false } } catch (e) { console.error('回答问题失败:', e) error.value = e instanceof Error ? e.message : '回答问题时发生错误' return false } finally { submitting.value = false } } // 公开提示 (主持人) async function revealHint(hintId: string) { if (!isHost.value || !hostView.value) { error.value = '主持人视图未加载' return false } submitting.value = true error.value = null try { const result = await turtleSoupService.revealHint(hostView.value.id, hintId) if (result.success) { // 更新本地状态 if (hostView.value) { const updatedHints = hostView.value.hints.map(hint => { if (hint.id === hintId) { return { ...hint, revealed: true, revealedAt: Date.now() } } return hint }) hostView.value = { ...hostView.value, hints: updatedHints } } return true } else { error.value = result.message || '公开提示失败' return false } } catch (e) { console.error('公开提示失败:', e) error.value = e instanceof Error ? e.message : '公开提示时发生错误' return false } finally { submitting.value = false } } // 提交解答 (玩家) async function submitSolution(solution: string) { if (!playerView.value || !solution.trim()) { error.value = '无效的解答或游戏未加载' return { success: false, correct: false } } submitting.value = true error.value = null try { const result = await turtleSoupService.submitSolution(playerView.value.id, solution) if (result.success) { // 解答正确 if (result.data?.correct) { return { success: true, correct: true } } // 解答错误 return { success: true, correct: false } } else { error.value = result.message || '提交解答失败' return { success: false, correct: false } } } catch (e) { console.error('提交解答失败:', e) error.value = e instanceof Error ? e.message : '提交解答时发生错误' return { success: false, correct: false } } finally { submitting.value = false } } // 结束游戏 - 只更新状态,不处理房间 async function endGame(params: { gameId: string, solved: boolean, solvedBy?: string, solvedByName?: string, solution?: string }) { submitting.value = true error.value = null try { const { gameId, ...resultData } = params const endResult = await turtleSoupService.endGame(gameId, resultData) if (endResult.success && endResult.data) { // 更新游戏状态 if (isHost.value && hostView.value && hostView.value.id === gameId) { hostView.value = { ...hostView.value, status: TurtleSoupGameStatus.COMPLETED, currentTime: Date.now() } } else if (playerView.value && playerView.value.id === gameId) { playerView.value = { ...playerView.value, status: TurtleSoupGameStatus.COMPLETED, currentTime: Date.now() } } return endResult.data } else { error.value = endResult.message || '结束游戏失败' return null } } catch (e) { console.error('结束游戏失败:', e) error.value = e instanceof Error ? e.message : '结束游戏时发生错误' return null } finally { submitting.value = false } } // 保存问题草稿 function saveDraft(content: string) { localDraft.value = content } // 更新游戏进度 (主持人) async function updateProgress(progress: number) { if (!isHost.value || !hostView.value) { error.value = '主持人视图未加载' return false } submitting.value = true try { const result = await turtleSoupService.updateProgress(hostView.value.id, progress) if (result.success) { if (hostView.value) { hostView.value = { ...hostView.value, progress } } return true } else { error.value = result.message || '更新游戏进度失败' return false } } catch (e) { console.error('更新游戏进度失败:', e) error.value = e instanceof Error ? e.message : '更新进度时发生错误' return false } finally { submitting.value = false } } // 刷新游戏数据 async function refreshGameData(gameId: string) { if (isHost.value) { return loadHostGame(gameId) } else { return loadPlayerGame(gameId) } } return { // 状态 hostView, playerView, loading, submitting, error, isHost, localDraft, gameSettings, availableThemes, availablePuzzles, // 计算属性 currentView, gameStatus, isGameActive, isGameEnded, revealedHints, unrevealedHints, sortedQuestions, pendingQuestions, myQuestions, gameDuration, gameProgress, roomCode, // 操作方法 resetState, setViewType, updateGameSettings, loadThemes, unlockTheme, loadPuzzles, createGame, loadHostGame, loadPlayerGame, gameStatusToRoomStatus, startGame, submitQuestion, answerQuestion, revealHint, submitSolution, endGame, saveDraft, updateProgress, refreshGameData } })