實作創意題與資料庫整合

This commit is contained in:
2025-09-29 03:24:17 +08:00
parent aa34d2d078
commit a3b46b4430
18 changed files with 1366 additions and 30 deletions

View File

@@ -0,0 +1,31 @@
import { NextRequest, NextResponse } from 'next/server'
import { getCreativeTestAnswersByTestResultId } from '@/lib/database/models/creative_test_answer'
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const testResultId = searchParams.get('testResultId')
if (!testResultId) {
return NextResponse.json(
{ success: false, error: '缺少測試結果ID' },
{ status: 400 }
)
}
// 獲取創意測驗答案
const answers = await getCreativeTestAnswersByTestResultId(testResultId)
return NextResponse.json({
success: true,
data: answers
})
} catch (error) {
console.error('獲取創意測驗答案失敗:', error)
return NextResponse.json(
{ success: false, error: '伺服器錯誤' },
{ status: 500 }
)
}
}

View File

@@ -0,0 +1,155 @@
import { NextRequest, NextResponse } from 'next/server'
import { createTestResult, getTestResultsByUserId } from '@/lib/database/models/test_result'
import { createCreativeTestAnswers } from '@/lib/database/models/creative_test_answer'
import { getAllCreativeQuestions } from '@/lib/database/models/creative_question'
export async function POST(request: NextRequest) {
let body: any
try {
body = await request.json()
const {
userId,
answers,
completedAt
} = body
// 驗證必要欄位
if (!userId || !answers || !completedAt) {
return NextResponse.json(
{ success: false, error: '缺少必要欄位' },
{ status: 400 }
)
}
// 獲取創意題目
const questions = await getAllCreativeQuestions()
if (questions.length === 0) {
return NextResponse.json(
{ success: false, error: '無法獲取題目' },
{ status: 500 }
)
}
// 計算分數(包含反向題處理)
let totalScore = 0
const answerRecords = []
for (let i = 0; i < questions.length; i++) {
const question = questions[i]
const userAnswer = answers[i] || 1 // 預設為1
// 處理反向題:如果是反向題,分數要反轉
let score = userAnswer
if (question.is_reverse) {
score = 6 - userAnswer // 5->1, 4->2, 3->3, 2->4, 1->5
}
totalScore += score
answerRecords.push({
test_result_id: '', // 稍後填入
question_id: question.id,
user_answer: userAnswer,
score: score
})
}
// 計算百分比分數
const maxPossibleScore = questions.length * 5 // 每題最高5分
const scorePercentage = Math.round((totalScore / maxPossibleScore) * 100)
// 建立測試結果
console.log('🔄 開始建立創意測驗結果...')
console.log('測試結果數據:', {
user_id: userId,
test_type: 'creative',
score: scorePercentage,
total_questions: questions.length,
correct_answers: totalScore, // 創意測驗用總分數代替正確答案數
completed_at: completedAt
})
const testResult = await createTestResult({
user_id: userId,
test_type: 'creative',
score: scorePercentage,
total_questions: questions.length,
correct_answers: totalScore,
completed_at: completedAt
})
console.log('測試結果建立結果:', testResult)
if (!testResult) {
console.error('❌ 建立測試結果失敗')
return NextResponse.json(
{ success: false, error: '建立測試結果失敗' },
{ status: 500 }
)
}
console.log('✅ 測試結果建立成功:', testResult.id)
// 更新答案記錄的 test_result_id
answerRecords.forEach(record => {
record.test_result_id = testResult.id
})
// 建立答案記錄
const answerResults = await createCreativeTestAnswers(answerRecords)
return NextResponse.json({
success: true,
data: {
testResult,
answerCount: answerResults.length
}
})
} catch (error) {
console.error('上傳創意測驗結果失敗:', error)
console.error('錯誤詳情:', {
message: error instanceof Error ? error.message : '未知錯誤',
stack: error instanceof Error ? error.stack : undefined,
body: body
})
return NextResponse.json(
{
success: false,
error: '伺服器錯誤',
details: error instanceof Error ? error.message : '未知錯誤'
},
{ status: 500 }
)
}
}
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url)
const userId = searchParams.get('userId')
if (!userId) {
return NextResponse.json(
{ success: false, error: '缺少用戶ID' },
{ status: 400 }
)
}
// 獲取用戶的創意測驗結果
const results = await getTestResultsByUserId(userId)
const creativeResults = results.filter(r => r.test_type === 'creative')
return NextResponse.json({
success: true,
data: creativeResults
})
} catch (error) {
console.error('獲取創意測驗結果失敗:', error)
return NextResponse.json(
{ success: false, error: '伺服器錯誤' },
{ status: 500 }
)
}
}

View File

@@ -8,6 +8,7 @@ import { Progress } from "@/components/ui/progress"
import { Lightbulb, Home, RotateCcw, TrendingUp } from "lucide-react" import { Lightbulb, Home, RotateCcw, TrendingUp } from "lucide-react"
import Link from "next/link" import Link from "next/link"
import { creativeQuestions } from "@/lib/questions/creative-questions" import { creativeQuestions } from "@/lib/questions/creative-questions"
import { useAuth } from "@/lib/hooks/use-auth"
interface CreativeTestResults { interface CreativeTestResults {
type: string type: string
@@ -16,17 +17,139 @@ interface CreativeTestResults {
maxScore: number maxScore: number
answers: Record<number, number> answers: Record<number, number>
completedAt: string completedAt: string
dimensionScores?: {
innovation: { percentage: number, rawScore: number, maxScore: number }
imagination: { percentage: number, rawScore: number, maxScore: number }
flexibility: { percentage: number, rawScore: number, maxScore: number }
originality: { percentage: number, rawScore: number, maxScore: number }
}
} }
export default function CreativeResultsPage() { export default function CreativeResultsPage() {
const { user } = useAuth()
const [results, setResults] = useState<CreativeTestResults | null>(null) const [results, setResults] = useState<CreativeTestResults | null>(null)
const [questions, setQuestions] = useState<any[]>([])
const [isLoading, setIsLoading] = useState(true)
useEffect(() => { useEffect(() => {
const loadData = async () => {
if (!user) return
try {
// 從資料庫獲取最新的創意測驗結果
const response = await fetch(`/api/test-results/creative?userId=${user.id}`)
const data = await response.json()
if (data.success && data.data.length > 0) {
// 取最新的結果
const latestResult = data.data[0]
// 獲取題目資料來計算各維度分數
const questionsResponse = await fetch('/api/creative-questions')
const questionsData = await questionsResponse.json()
if (questionsData.success) {
setQuestions(questionsData.questions)
// 計算各維度分數
const dimensionScores = await calculateDimensionScores(latestResult, questionsData.questions)
setResults({
type: "creative",
score: latestResult.score,
totalScore: latestResult.correct_answers,
maxScore: latestResult.total_questions * 5,
answers: {}, // 從資料庫結果中獲取
completedAt: latestResult.completed_at,
dimensionScores: dimensionScores
})
}
} else {
// 如果沒有資料庫結果,回退到 localStorage
const savedResults = localStorage.getItem("creativeTestResults") const savedResults = localStorage.getItem("creativeTestResults")
if (savedResults) { if (savedResults) {
setResults(JSON.parse(savedResults)) setResults(JSON.parse(savedResults))
} }
}, []) }
} catch (error) {
console.error('Error loading creative test results:', error)
// 回退到 localStorage
const savedResults = localStorage.getItem("creativeTestResults")
if (savedResults) {
setResults(JSON.parse(savedResults))
}
} finally {
setIsLoading(false)
}
}
loadData()
}, [user])
// 計算各維度分數
const calculateDimensionScores = async (testResult: any, questions: any[]) => {
try {
// 獲取詳細答案
const answersResponse = await fetch(`/api/creative-test-answers?testResultId=${testResult.id}`)
const answersData = await answersResponse.json()
if (!answersData.success) {
return {
innovation: { percentage: 0, rawScore: 0, maxScore: 0 },
imagination: { percentage: 0, rawScore: 0, maxScore: 0 },
flexibility: { percentage: 0, rawScore: 0, maxScore: 0 },
originality: { percentage: 0, rawScore: 0, maxScore: 0 }
}
}
const answers = answersData.data
const dimensionScores: Record<string, { total: number, count: number }> = {
innovation: { total: 0, count: 0 },
imagination: { total: 0, count: 0 },
flexibility: { total: 0, count: 0 },
originality: { total: 0, count: 0 }
}
// 計算各維度分數
answers.forEach((answer: any) => {
const question = questions.find(q => q.id === answer.question_id)
if (question && dimensionScores[question.category]) {
dimensionScores[question.category].total += answer.score
dimensionScores[question.category].count += 1
}
})
// 計算百分比分數和原始分數
const result = {
innovation: { percentage: 0, rawScore: 0, maxScore: 0 },
imagination: { percentage: 0, rawScore: 0, maxScore: 0 },
flexibility: { percentage: 0, rawScore: 0, maxScore: 0 },
originality: { percentage: 0, rawScore: 0, maxScore: 0 }
}
Object.keys(dimensionScores).forEach(category => {
const { total, count } = dimensionScores[category]
const maxScore = count * 5
const percentage = count > 0 ? Math.round((total / maxScore) * 100) : 0
result[category as keyof typeof result] = {
percentage: percentage,
rawScore: total,
maxScore: maxScore
}
})
return result
} catch (error) {
console.error('計算維度分數失敗:', error)
return {
innovation: { percentage: 0, rawScore: 0, maxScore: 0 },
imagination: { percentage: 0, rawScore: 0, maxScore: 0 },
flexibility: { percentage: 0, rawScore: 0, maxScore: 0 },
originality: { percentage: 0, rawScore: 0, maxScore: 0 }
}
}
}
if (!results) { if (!results) {
return ( return (
@@ -78,7 +201,33 @@ export default function CreativeResultsPage() {
const creativityLevel = getCreativityLevel(results.score) const creativityLevel = getCreativityLevel(results.score)
// Calculate category scores // Calculate category scores - prioritize database data if available
let categoryResults: Array<{
category: string
name: string
score: number
rawScore: number
maxRawScore: number
}> = []
if (results.dimensionScores) {
// Use database-calculated dimension scores
const dimensionNames = {
innovation: '創新能力',
imagination: '想像力',
flexibility: '靈活性',
originality: '原創性'
}
categoryResults = Object.entries(results.dimensionScores).map(([key, data]) => ({
category: key,
name: dimensionNames[key as keyof typeof dimensionNames],
score: data.percentage,
rawScore: data.rawScore,
maxRawScore: data.maxScore
}))
} else {
// Fallback to localStorage calculation
const categoryScores = { const categoryScores = {
innovation: { total: 0, count: 0, name: "創新能力" }, innovation: { total: 0, count: 0, name: "創新能力" },
imagination: { total: 0, count: 0, name: "想像力" }, imagination: { total: 0, count: 0, name: "想像力" },
@@ -93,13 +242,14 @@ export default function CreativeResultsPage() {
categoryScores[question.category].count += 1 categoryScores[question.category].count += 1
}) })
const categoryResults = Object.entries(categoryScores).map(([key, data]) => ({ categoryResults = Object.entries(categoryScores).map(([key, data]) => ({
category: key, category: key,
name: data.name, name: data.name,
score: data.count > 0 ? Math.round((data.total / (data.count * 5)) * 100) : 0, score: data.count > 0 ? Math.round((data.total / (data.count * 5)) * 100) : 0,
rawScore: data.total, rawScore: data.total,
maxRawScore: data.count * 5, maxRawScore: data.count * 5,
})) }))
}
return ( return (
<div className="min-h-screen bg-background"> <div className="min-h-screen bg-background">

View File

@@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation"
import { useAuth } from "@/lib/hooks/use-auth"
interface CreativeQuestion { interface CreativeQuestion {
id: number id: number
@@ -18,11 +19,13 @@ interface CreativeQuestion {
export default function CreativeTestPage() { export default function CreativeTestPage() {
const router = useRouter() const router = useRouter()
const { user } = useAuth()
const [questions, setQuestions] = useState<CreativeQuestion[]>([]) const [questions, setQuestions] = useState<CreativeQuestion[]>([])
const [currentQuestion, setCurrentQuestion] = useState(0) const [currentQuestion, setCurrentQuestion] = useState(0)
const [answers, setAnswers] = useState<Record<number, number>>({}) const [answers, setAnswers] = useState<Record<number, number>>({})
const [timeRemaining, setTimeRemaining] = useState(30 * 60) // 30 minutes in seconds const [timeRemaining, setTimeRemaining] = useState(30 * 60) // 30 minutes in seconds
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)
const [isSubmitting, setIsSubmitting] = useState(false)
// Load questions from database // Load questions from database
useEffect(() => { useEffect(() => {
@@ -88,7 +91,20 @@ export default function CreativeTestPage() {
} }
} }
const handleSubmit = () => { const handleSubmit = async () => {
console.log('🔍 開始提交創意測驗...')
console.log('用戶狀態:', user)
if (!user) {
console.log('❌ 用戶未登入')
alert('請先登入')
return
}
console.log('✅ 用戶已登入用戶ID:', user.id)
setIsSubmitting(true)
try {
// Calculate score based on creativity scoring // Calculate score based on creativity scoring
let totalScore = 0 let totalScore = 0
questions.forEach((question, index) => { questions.forEach((question, index) => {
@@ -101,7 +117,7 @@ export default function CreativeTestPage() {
const maxScore = questions.length * 5 const maxScore = questions.length * 5
const score = Math.round((totalScore / maxScore) * 100) const score = Math.round((totalScore / maxScore) * 100)
// Store results in localStorage // Store results in localStorage (for backward compatibility)
const results = { const results = {
type: "creative", type: "creative",
score, score,
@@ -112,7 +128,46 @@ export default function CreativeTestPage() {
} }
localStorage.setItem("creativeTestResults", JSON.stringify(results)) localStorage.setItem("creativeTestResults", JSON.stringify(results))
console.log('✅ 結果已儲存到 localStorage')
// Upload to database
console.log('🔄 開始上傳到資料庫...')
const uploadData = {
userId: user.id,
answers: Object.values(answers),
completedAt: new Date().toISOString().replace('Z', '').replace('T', ' ')
}
console.log('上傳數據:', uploadData)
const uploadResponse = await fetch('/api/test-results/creative', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(uploadData)
})
console.log('📡 API 響應狀態:', uploadResponse.status)
const uploadResult = await uploadResponse.json()
console.log('📡 API 響應內容:', uploadResult)
if (uploadResult.success) {
console.log('✅ 創意測驗結果已上傳到資料庫')
console.log('測試結果ID:', uploadResult.data.testResult.id)
console.log('答案記錄數量:', uploadResult.data.answerCount)
} else {
console.error('❌ 上傳到資料庫失敗:', uploadResult.error)
// 即使上傳失敗,也繼續顯示結果
}
router.push("/results/creative") router.push("/results/creative")
} catch (error) {
console.error('❌ 提交測驗失敗:', error)
alert('提交測驗失敗,請重試')
} finally {
setIsSubmitting(false)
}
} }
if (isLoading) { if (isLoading) {
@@ -223,8 +278,8 @@ export default function CreativeTestPage() {
</div> </div>
{isLastQuestion ? ( {isLastQuestion ? (
<Button onClick={handleSubmit} disabled={!hasAnswer} className="bg-green-600 hover:bg-green-700"> <Button onClick={handleSubmit} disabled={!hasAnswer || isSubmitting} className="bg-green-600 hover:bg-green-700">
{isSubmitting ? '提交中...' : '提交測試'}
</Button> </Button>
) : ( ) : (
<Button onClick={handleNext} disabled={!hasAnswer}> <Button onClick={handleNext} disabled={!hasAnswer}>

View File

@@ -4,6 +4,7 @@ import { createLogicQuestionsTable } from './models/logic_question'
import { createCreativeQuestionsTable } from './models/creative_question' import { createCreativeQuestionsTable } from './models/creative_question'
import { createTestResultsTable } from './models/test_result' import { createTestResultsTable } from './models/test_result'
import { createLogicTestAnswersTable } from './models/logic_test_answer' import { createLogicTestAnswersTable } from './models/logic_test_answer'
import { createCreativeTestAnswersTable } from './models/creative_test_answer'
// 初始化資料庫 // 初始化資料庫
export async function initializeDatabase(): Promise<boolean> { export async function initializeDatabase(): Promise<boolean> {
@@ -32,6 +33,9 @@ export async function initializeDatabase(): Promise<boolean> {
// 建立邏輯測驗答案表 // 建立邏輯測驗答案表
await createLogicTestAnswersTable() await createLogicTestAnswersTable()
// 建立創意測驗答案表
await createCreativeTestAnswersTable()
console.log('✅ 資料庫初始化完成') console.log('✅ 資料庫初始化完成')
return true return true
} catch (error) { } catch (error) {

View File

@@ -60,7 +60,7 @@ export async function findCreativeQuestionById(id: number): Promise<CreativeQues
// 獲取所有題目 // 獲取所有題目
export async function getAllCreativeQuestions(): Promise<CreativeQuestion[]> { export async function getAllCreativeQuestions(): Promise<CreativeQuestion[]> {
const query = 'SELECT * FROM creative_questions ORDER BY created_at' const query = 'SELECT * FROM creative_questions ORDER BY created_at'
return await executeQuery<CreativeQuestion[]>(query) return await executeQuery<CreativeQuestion>(query)
} }
// 清空所有題目 // 清空所有題目

View File

@@ -0,0 +1,91 @@
import { executeQuery } from '../connection'
import { v4 as uuidv4 } from 'uuid'
export interface CreativeTestAnswer {
id: string
test_result_id: string
question_id: number
user_answer: number // 1-5 Likert scale
score: number // 計算後的分數(考慮反向題)
created_at?: string
}
export interface CreateCreativeTestAnswerData {
test_result_id: string
question_id: number
user_answer: number
score: number
}
// 建立創意測驗答案表(如果不存在)
export async function createCreativeTestAnswersTable(): Promise<void> {
const createTableQuery = `
CREATE TABLE IF NOT EXISTS creative_test_answers (
id VARCHAR(50) PRIMARY KEY,
test_result_id VARCHAR(50) NOT NULL,
question_id INT NOT NULL,
user_answer TINYINT NOT NULL,
score INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_test_result_id (test_result_id),
INDEX idx_question_id (question_id),
FOREIGN KEY (test_result_id) REFERENCES test_results(id) ON DELETE CASCADE,
FOREIGN KEY (question_id) REFERENCES creative_questions(id) ON DELETE CASCADE
)
`
await executeQuery(createTableQuery)
console.log('✅ 創意測驗答案表建立成功')
}
// 批量建立創意測驗答案
export async function createCreativeTestAnswers(answers: CreateCreativeTestAnswerData[]): Promise<CreativeTestAnswer[]> {
if (answers.length === 0) {
return []
}
const placeholders = answers.map(() => '(?, ?, ?, ?, ?)').join(', ')
const values: any[] = []
answers.forEach(answer => {
values.push(
`answer_${Date.now()}_${uuidv4().substring(0, 9)}`, // Generate unique ID for each answer
answer.test_result_id,
answer.question_id,
answer.user_answer,
answer.score
)
})
const insertQuery = `
INSERT INTO creative_test_answers (id, test_result_id, question_id, user_answer, score)
VALUES ${placeholders}
`
try {
await executeQuery(insertQuery, values)
// For simplicity, we're not fetching each inserted answer.
// In a real app, you might fetch them or return a success status.
return answers.map(ans => ({ ...ans, id: `answer_${Date.now()}_${uuidv4().substring(0, 9)}` })) // Dummy IDs for return
} catch (error) {
console.error('建立創意測驗答案失敗:', error)
throw error
}
}
// 根據測試結果ID獲取所有答案
export async function getCreativeTestAnswersByTestResultId(testResultId: string): Promise<CreativeTestAnswer[]> {
try {
const query = 'SELECT * FROM creative_test_answers WHERE test_result_id = ? ORDER BY created_at ASC'
return await executeQuery<CreativeTestAnswer>(query, [testResultId])
} catch (error) {
console.error('獲取創意測驗答案失敗:', error)
return []
}
}
// 清空所有創意測驗答案
export async function clearCreativeTestAnswers(): Promise<void> {
await executeQuery('DELETE FROM creative_test_answers')
console.log('✅ 已清空所有創意測驗答案')
}

21
package-lock.json generated
View File

@@ -36,6 +36,7 @@
"@radix-ui/react-toggle": "1.1.1", "@radix-ui/react-toggle": "1.1.1",
"@radix-ui/react-toggle-group": "1.1.1", "@radix-ui/react-toggle-group": "1.1.1",
"@radix-ui/react-tooltip": "1.1.6", "@radix-ui/react-tooltip": "1.1.6",
"@types/uuid": "^10.0.0",
"@vercel/analytics": "1.3.1", "@vercel/analytics": "1.3.1",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
@@ -61,6 +62,7 @@
"sonner": "^1.7.4", "sonner": "^1.7.4",
"tailwind-merge": "^2.5.5", "tailwind-merge": "^2.5.5",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"uuid": "^13.0.0",
"vaul": "^0.9.9", "vaul": "^0.9.9",
"xlsx": "latest", "xlsx": "latest",
"zod": "3.25.67" "zod": "3.25.67"
@@ -2373,6 +2375,12 @@
"@types/react": "^18.0.0" "@types/react": "^18.0.0"
} }
}, },
"node_modules/@types/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
"license": "MIT"
},
"node_modules/@vercel/analytics": { "node_modules/@vercel/analytics": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.3.1.tgz", "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.3.1.tgz",
@@ -4254,6 +4262,19 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
} }
}, },
"node_modules/uuid": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
"integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist-node/bin/uuid"
}
},
"node_modules/vaul": { "node_modules/vaul": {
"version": "0.9.9", "version": "0.9.9",
"resolved": "https://registry.npmjs.org/vaul/-/vaul-0.9.9.tgz", "resolved": "https://registry.npmjs.org/vaul/-/vaul-0.9.9.tgz",

View File

@@ -78,6 +78,7 @@
"@radix-ui/react-toggle": "1.1.1", "@radix-ui/react-toggle": "1.1.1",
"@radix-ui/react-toggle-group": "1.1.1", "@radix-ui/react-toggle-group": "1.1.1",
"@radix-ui/react-tooltip": "1.1.6", "@radix-ui/react-tooltip": "1.1.6",
"@types/uuid": "^10.0.0",
"@vercel/analytics": "1.3.1", "@vercel/analytics": "1.3.1",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
@@ -103,6 +104,7 @@
"sonner": "^1.7.4", "sonner": "^1.7.4",
"tailwind-merge": "^2.5.5", "tailwind-merge": "^2.5.5",
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"uuid": "^13.0.0",
"vaul": "^0.9.9", "vaul": "^0.9.9",
"xlsx": "latest", "xlsx": "latest",
"zod": "3.25.67" "zod": "3.25.67"

View File

@@ -0,0 +1,49 @@
const mysql = require('mysql2/promise')
async function checkCreativeQuestionsTable() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查 creative_questions 表結構...')
let connection
try {
connection = await mysql.createConnection(config)
// 檢查表結構
const [columns] = await connection.execute("DESCRIBE creative_questions")
console.log('\n📊 creative_questions 表結構:')
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
// 檢查表內容
const [rows] = await connection.execute("SELECT * FROM creative_questions LIMIT 3")
console.log('\n📝 creative_questions 表內容 (前3筆):')
if (rows.length > 0) {
rows.forEach((row, index) => {
console.log(`${index + 1}. ID: ${row.id}`)
console.log(` 題目: ${row.statement}`)
console.log(` 類別: ${row.category}`)
console.log(` 是否反向: ${row.is_reverse}`)
console.log('')
})
} else {
console.log('❌ 沒有找到創意題目數據')
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
if (connection) {
await connection.end()
}
}
}
checkCreativeQuestionsTable()

View File

@@ -0,0 +1,41 @@
const mysql = require('mysql2/promise')
async function checkCreativeTestAnswersTable() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查 creative_test_answers 表結構...')
let connection
try {
connection = await mysql.createConnection(config)
// 檢查表是否存在
const [tables] = await connection.execute("SHOW TABLES LIKE 'creative_test_answers'")
if (tables.length === 0) {
console.log('❌ creative_test_answers 表不存在')
return
}
// 檢查表結構
const [columns] = await connection.execute("DESCRIBE creative_test_answers")
console.log('\n📊 creative_test_answers 表結構:')
columns.forEach(col => {
console.log(`- ${col.Field}: ${col.Type} ${col.Null === 'NO' ? 'NOT NULL' : 'NULL'} ${col.Key ? `(${col.Key})` : ''}`)
})
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
if (connection) {
await connection.end()
}
}
}
checkCreativeTestAnswersTable()

View File

@@ -0,0 +1,84 @@
const mysql = require('mysql2/promise')
async function checkCreativeTestResults() {
const config = {
host: process.env.DB_HOST || 'mysql.theaken.com',
port: parseInt(process.env.DB_PORT || '33306'),
user: process.env.DB_USER || 'hr_assessment',
password: process.env.DB_PASSWORD || 'QFOts8FlibiI',
database: process.env.DB_NAME || 'db_hr_assessment',
}
console.log('🔍 檢查創意測驗結果...')
let connection
try {
connection = await mysql.createConnection(config)
// 檢查 test_results 表中的創意測驗結果
const [creativeResults] = await connection.execute(
`SELECT tr.*, u.name as user_name
FROM test_results tr
JOIN users u ON tr.user_id = u.id
WHERE tr.test_type = 'creative'
ORDER BY tr.completed_at DESC`
)
console.log('\n📊 test_results 表中的創意測驗結果:')
if (creativeResults.length > 0) {
console.log(`找到 ${creativeResults.length} 筆創意測驗結果:`)
creativeResults.forEach((result, index) => {
console.log(`${index + 1}. ID: ${result.id}`)
console.log(` 用戶ID: ${result.user_id}`)
console.log(` 用戶名稱: ${result.user_name}`)
console.log(` 分數: ${result.score}`)
console.log(` 總分數: ${result.correct_answers}`)
console.log(` 總題數: ${result.total_questions}`)
console.log(` 完成時間: ${new Date(result.completed_at)}`)
console.log(` 建立時間: ${new Date(result.created_at)}`)
console.log('')
})
} else {
console.log('❌ 沒有找到創意測驗結果')
}
// 檢查 creative_test_answers 表中的答案記錄
const [answerRecords] = await connection.execute(
`SELECT cta.*, u.id as user_id, cq.statement as question_text, cq.is_reverse
FROM creative_test_answers cta
JOIN test_results tr ON cta.test_result_id = tr.id
JOIN users u ON tr.user_id = u.id
JOIN creative_questions cq ON cta.question_id = cq.id
ORDER BY cta.created_at ASC
LIMIT 10`
)
console.log('\n📝 creative_test_answers 表中的答案記錄 (前10筆):')
if (answerRecords.length > 0) {
console.log(`找到 ${answerRecords.length} 筆答案記錄:`)
answerRecords.forEach((record, index) => {
console.log(`${index + 1}. 答案ID: ${record.id}`)
console.log(` 測試結果ID: ${record.test_result_id}`)
console.log(` 用戶ID: ${record.user_id}`)
console.log(` 題目ID: ${record.question_id}`)
console.log(` 題目: ${record.question_text}`)
console.log(` 用戶答案: ${record.user_answer}`)
console.log(` 計算分數: ${record.score}`)
console.log(` 是否反向題: ${record.is_reverse ? '是' : '否'}`)
console.log(` 建立時間: ${new Date(record.created_at)}`)
console.log('')
})
} else {
console.log('❌ 沒有找到答案記錄')
}
} catch (error) {
console.error('❌ 檢查失敗:', error.message)
} finally {
if (connection) {
await connection.end()
}
}
}
checkCreativeTestResults()

View File

@@ -0,0 +1,132 @@
const https = require('https')
const http = require('http')
const debugDimensionScoring = async () => {
console.log('🔍 調試維度分數計算')
console.log('=' .repeat(50))
const testResultId = 'test_1759086508812_xv2pof6lk' // 使用最新的測試結果ID
try {
// 1. 獲取測試結果
console.log('\n📊 1. 獲取測試結果...')
const resultResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=user-1759073326705-m06y3wacd`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (resultResponse.status === 200) {
const resultData = JSON.parse(resultResponse.data)
if (resultData.success && resultData.data.length > 0) {
const testResult = resultData.data[0]
console.log('測試結果:', {
id: testResult.id,
score: testResult.score,
total_questions: testResult.total_questions,
correct_answers: testResult.correct_answers
})
}
}
// 2. 獲取題目資料
console.log('\n📊 2. 獲取題目資料...')
const questionsResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/creative-questions', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let questions = []
if (questionsResponse.status === 200) {
const questionsData = JSON.parse(questionsResponse.data)
if (questionsData.success) {
questions = questionsData.questions
console.log(`獲取到 ${questions.length} 個題目`)
}
}
// 3. 獲取詳細答案
console.log('\n📊 3. 獲取詳細答案...')
const answersResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (answersResponse.status === 200) {
const answersData = JSON.parse(answersResponse.data)
if (answersData.success) {
const answers = answersData.data
console.log(`獲取到 ${answers.length} 個答案`)
// 4. 按維度分組計算
console.log('\n📊 4. 按維度分組計算...')
const dimensionScores = {
innovation: { total: 0, count: 0, answers: [] },
imagination: { total: 0, count: 0, answers: [] },
flexibility: { total: 0, count: 0, answers: [] },
originality: { total: 0, count: 0, answers: [] }
}
answers.forEach((answer) => {
const question = questions.find(q => q.id === answer.question_id)
if (question && dimensionScores[question.category]) {
dimensionScores[question.category].total += answer.score
dimensionScores[question.category].count += 1
dimensionScores[question.category].answers.push({
question_id: answer.question_id,
user_answer: answer.user_answer,
score: answer.score,
is_reverse: question.is_reverse
})
}
})
// 5. 顯示詳細計算過程
console.log('\n📊 5. 詳細計算過程:')
Object.keys(dimensionScores).forEach(category => {
const { total, count, answers } = dimensionScores[category]
const maxPossible = count * 5
const percentage = count > 0 ? Math.round((total / maxPossible) * 100) : 0
console.log(`\n${category}:`)
console.log(` 題目數量: ${count}`)
console.log(` 總分數: ${total}`)
console.log(` 最大可能分數: ${maxPossible}`)
console.log(` 百分比: ${percentage}%`)
console.log(` 答案詳情:`)
answers.forEach((ans, index) => {
console.log(` ${index + 1}. 題目${ans.question_id}: 用戶答案${ans.user_answer} → 計算分數${ans.score} (反向題: ${ans.is_reverse ? '是' : '否'})`)
})
})
// 6. 總分驗證
console.log('\n📊 6. 總分驗證:')
const totalScore = answers.reduce((sum, answer) => sum + answer.score, 0)
const maxTotalScore = answers.length * 5
const totalPercentage = Math.round((totalScore / maxTotalScore) * 100)
console.log(`所有答案總分數: ${totalScore}`)
console.log(`最大可能總分數: ${maxTotalScore}`)
console.log(`總百分比: ${totalPercentage}%`)
}
}
} catch (error) {
console.error('❌ 調試失敗:', error.message)
} finally {
console.log('\n✅ 維度分數計算調試完成')
}
}
debugDimensionScoring()

View File

@@ -0,0 +1,61 @@
const https = require('https')
const http = require('http')
const testCreativeAnswersAPI = async () => {
console.log('🧪 測試創意測驗答案 API')
console.log('=' .repeat(50))
const testResultId = 'test_1759086508812_xv2pof6lk' // 使用最新的測試結果ID
const url = `http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`
try {
console.log(`\n📊 測試結果ID: ${testResultId}`)
console.log(`🔗 API URL: ${url}`)
const response = await new Promise((resolve, reject) => {
const req = http.get(url, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
console.log('📊 響應狀態:', response.status)
if (response.status === 200) {
const result = JSON.parse(response.data)
console.log('\n✅ API 測試成功!')
console.log('📡 響應內容:', JSON.stringify(result, null, 2))
if (result.success) {
console.log(`\n📈 答案記錄詳情:`)
console.log(`- 答案數量: ${result.data.length}`)
// 按維度分組統計
const dimensionStats = {
innovation: { total: 0, count: 0 },
imagination: { total: 0, count: 0 },
flexibility: { total: 0, count: 0 },
originality: { total: 0, count: 0 }
}
result.data.forEach((answer, index) => {
console.log(`${index + 1}. 題目ID: ${answer.question_id}, 用戶答案: ${answer.user_answer}, 計算分數: ${answer.score}`)
})
}
} else {
console.log('❌ API 響應失敗,狀態碼:', response.status)
console.log('響應內容:', response.data)
}
} catch (error) {
console.error('\n❌ 請求失敗:')
console.error('錯誤類型:', error.name)
console.error('錯誤訊息:', error.message)
} finally {
console.log('\n✅ 創意測驗答案 API 測試完成')
}
}
testCreativeAnswersAPI()

View File

@@ -0,0 +1,79 @@
const https = require('https')
const http = require('http')
const testCreativeDBUpload = async () => {
console.log('🧪 測試創意測驗資料庫上傳功能')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd' // 使用現有用戶ID
const url = 'http://localhost:3000/api/test-results/creative'
// 模擬創意測驗答案1-5分包含反向題
const testAnswers = [
5, 4, 3, 2, 1, // 前5題正常題
1, 2, 3, 4, 5, // 中間5題反向題會自動反轉
5, 4, 3, 2, 1, // 後8題正常題
1, 2, 3, 4, 5
]
const testData = {
userId: userId,
answers: testAnswers,
completedAt: new Date().toISOString().replace('Z', '').replace('T', ' ')
}
console.log('\n📝 測試數據:')
console.log('用戶ID:', testData.userId)
console.log('答案數量:', testData.answers.length)
console.log('答案內容:', testData.answers)
console.log('完成時間:', testData.completedAt)
try {
console.log('\n🔄 測試創意測驗 API...')
const response = await new Promise((resolve, reject) => {
const req = http.request(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
}, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
req.write(JSON.stringify(testData))
req.end()
})
console.log('📊 響應狀態:', response.status)
if (response.status === 200) {
const result = JSON.parse(response.data)
console.log('\n✅ API 測試成功!')
console.log('📡 響應內容:', JSON.stringify(result, null, 2))
if (result.success) {
console.log('\n📈 測試結果詳情:')
console.log('- 測試結果ID:', result.data.testResult.id)
console.log('- 分數:', result.data.testResult.score)
console.log('- 總題數:', result.data.testResult.total_questions)
console.log('- 總分數:', result.data.testResult.correct_answers)
console.log('- 答案記錄數量:', result.data.answerCount)
}
} else {
console.log('❌ API 響應失敗,狀態碼:', response.status)
console.log('響應內容:', response.data)
}
} catch (error) {
console.error('\n❌ 請求失敗:')
console.error('錯誤類型:', error.name)
console.error('錯誤訊息:', error.message)
} finally {
console.log('\n✅ 創意測驗資料庫上傳測試完成')
}
}
testCreativeDBUpload()

View File

@@ -0,0 +1,67 @@
const https = require('https')
const http = require('http')
const testCreativeResultsPage = async () => {
console.log('🧪 測試創意測驗結果頁面數據獲取')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
try {
// 1. 測試用戶測試結果 API
console.log('\n📊 1. 測試用戶測試結果 API...')
const userResultsResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/user/test-results?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (userResultsResponse.status === 200) {
const userResultsData = JSON.parse(userResultsResponse.data)
console.log('用戶測試結果:', JSON.stringify(userResultsData, null, 2))
}
// 2. 測試創意測驗結果 API
console.log('\n📊 2. 測試創意測驗結果 API...')
const creativeResultsResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (creativeResultsResponse.status === 200) {
const creativeResultsData = JSON.parse(creativeResultsResponse.data)
console.log('創意測驗結果:', JSON.stringify(creativeResultsData, null, 2))
}
// 3. 測試創意測驗答案 API
console.log('\n📊 3. 測試創意測驗答案 API...')
const testResultId = 'test_1759086508812_xv2pof6lk'
const answersResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (answersResponse.status === 200) {
const answersData = JSON.parse(answersResponse.data)
console.log('創意測驗答案數量:', answersData.data.length)
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 創意測驗結果頁面數據獲取測試完成')
}
}
testCreativeResultsPage()

View File

@@ -0,0 +1,156 @@
const https = require('https')
const http = require('http')
const testFixedDimensionDisplay = async () => {
console.log('🧪 測試修正後的維度分數顯示')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
const testResultId = 'test_1759086508812_xv2pof6lk'
try {
// 1. 獲取測試結果
console.log('\n📊 1. 獲取測試結果...')
const resultResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let testResult = null
if (resultResponse.status === 200) {
const resultData = JSON.parse(resultResponse.data)
if (resultData.success && resultData.data.length > 0) {
testResult = resultData.data[0]
console.log('測試結果:', {
id: testResult.id,
score: testResult.score,
total_questions: testResult.total_questions,
correct_answers: testResult.correct_answers
})
}
}
// 2. 獲取題目資料
console.log('\n📊 2. 獲取題目資料...')
const questionsResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/creative-questions', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let questions = []
if (questionsResponse.status === 200) {
const questionsData = JSON.parse(questionsResponse.data)
if (questionsData.success) {
questions = questionsData.questions
console.log(`獲取到 ${questions.length} 個題目`)
}
}
// 3. 獲取詳細答案
console.log('\n📊 3. 獲取詳細答案...')
const answersResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (answersResponse.status === 200) {
const answersData = JSON.parse(answersResponse.data)
if (answersData.success) {
const answers = answersData.data
console.log(`獲取到 ${answers.length} 個答案`)
// 4. 模擬新的維度分數計算
console.log('\n📊 4. 模擬新的維度分數計算...')
const dimensionScores = {
innovation: { total: 0, count: 0 },
imagination: { total: 0, count: 0 },
flexibility: { total: 0, count: 0 },
originality: { total: 0, count: 0 }
}
answers.forEach((answer) => {
const question = questions.find(q => q.id === answer.question_id)
if (question && dimensionScores[question.category]) {
dimensionScores[question.category].total += answer.score
dimensionScores[question.category].count += 1
}
})
// 計算新的維度分數結構
const calculatedDimensionScores = {
innovation: { percentage: 0, rawScore: 0, maxScore: 0 },
imagination: { percentage: 0, rawScore: 0, maxScore: 0 },
flexibility: { percentage: 0, rawScore: 0, maxScore: 0 },
originality: { percentage: 0, rawScore: 0, maxScore: 0 }
}
Object.keys(dimensionScores).forEach(category => {
const { total, count } = dimensionScores[category]
const maxScore = count * 5
const percentage = count > 0 ? Math.round((total / maxScore) * 100) : 0
calculatedDimensionScores[category] = {
percentage: percentage,
rawScore: total,
maxScore: maxScore
}
})
console.log('\n📈 新的維度分數結構:')
Object.entries(calculatedDimensionScores).forEach(([category, data]) => {
console.log(`${category}:`)
console.log(` 百分比: ${data.percentage}%`)
console.log(` 原始分數: ${data.rawScore}`)
console.log(` 滿分: ${data.maxScore}`)
console.log(` 顯示: ${data.rawScore}/${data.maxScore}`)
})
// 5. 模擬 categoryResults 計算
console.log('\n📊 5. 模擬 categoryResults 計算...')
const dimensionNames = {
innovation: '創新能力',
imagination: '想像力',
flexibility: '靈活性',
originality: '原創性'
}
const categoryResults = Object.entries(calculatedDimensionScores).map(([key, data]) => ({
category: key,
name: dimensionNames[key],
score: data.percentage,
rawScore: data.rawScore,
maxRawScore: data.maxScore
}))
console.log('\n📈 categoryResults:')
categoryResults.forEach(category => {
console.log(`${category.name}:`)
console.log(` 分數: ${category.score}`)
console.log(` 顯示: ${category.rawScore}/${category.maxRawScore}`)
})
}
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的維度分數顯示測試完成')
}
}
testFixedDimensionDisplay()

View File

@@ -0,0 +1,158 @@
const https = require('https')
const http = require('http')
const testFixedDimensionScoring = async () => {
console.log('🧪 測試修正後的維度分數計算')
console.log('=' .repeat(50))
const userId = 'user-1759073326705-m06y3wacd'
const testResultId = 'test_1759086508812_xv2pof6lk'
try {
// 1. 獲取測試結果
console.log('\n📊 1. 獲取測試結果...')
const resultResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/test-results/creative?userId=${userId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let testResult = null
if (resultResponse.status === 200) {
const resultData = JSON.parse(resultResponse.data)
if (resultData.success && resultData.data.length > 0) {
testResult = resultData.data[0]
console.log('測試結果:', {
id: testResult.id,
score: testResult.score,
total_questions: testResult.total_questions,
correct_answers: testResult.correct_answers
})
}
}
// 2. 獲取題目資料
console.log('\n📊 2. 獲取題目資料...')
const questionsResponse = await new Promise((resolve, reject) => {
const req = http.get('http://localhost:3000/api/creative-questions', (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
let questions = []
if (questionsResponse.status === 200) {
const questionsData = JSON.parse(questionsResponse.data)
if (questionsData.success) {
questions = questionsData.questions
console.log(`獲取到 ${questions.length} 個題目`)
}
}
// 3. 獲取詳細答案
console.log('\n📊 3. 獲取詳細答案...')
const answersResponse = await new Promise((resolve, reject) => {
const req = http.get(`http://localhost:3000/api/creative-test-answers?testResultId=${testResultId}`, (res) => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => resolve({ status: res.statusCode, data }))
})
req.on('error', reject)
})
if (answersResponse.status === 200) {
const answersData = JSON.parse(answersResponse.data)
if (answersData.success) {
const answers = answersData.data
console.log(`獲取到 ${answers.length} 個答案`)
// 4. 模擬結果頁面的維度分數計算
console.log('\n📊 4. 模擬結果頁面的維度分數計算...')
// 計算各維度分數(模擬資料庫計算)
const dimensionScores = {
innovation: { total: 0, count: 0 },
imagination: { total: 0, count: 0 },
flexibility: { total: 0, count: 0 },
originality: { total: 0, count: 0 }
}
answers.forEach((answer) => {
const question = questions.find(q => q.id === answer.question_id)
if (question && dimensionScores[question.category]) {
dimensionScores[question.category].total += answer.score
dimensionScores[question.category].count += 1
}
})
// 計算百分比分數
const calculatedDimensionScores = {
innovation: 0,
imagination: 0,
flexibility: 0,
originality: 0
}
Object.keys(dimensionScores).forEach(category => {
const { total, count } = dimensionScores[category]
calculatedDimensionScores[category] =
count > 0 ? Math.round((total / (count * 5)) * 100) : 0
})
console.log('\n📈 計算結果:')
console.log('創新能力:', calculatedDimensionScores.innovation + '%')
console.log('想像力:', calculatedDimensionScores.imagination + '%')
console.log('靈活性:', calculatedDimensionScores.flexibility + '%')
console.log('原創性:', calculatedDimensionScores.originality + '%')
// 5. 模擬結果頁面的 categoryResults 計算
console.log('\n📊 5. 模擬結果頁面的 categoryResults 計算...')
const dimensionNames = {
innovation: '創新能力',
imagination: '想像力',
flexibility: '靈活性',
originality: '原創性'
}
const categoryResults = Object.entries(calculatedDimensionScores).map(([key, score]) => ({
category: key,
name: dimensionNames[key],
score: score,
rawScore: 0,
maxRawScore: 0
}))
console.log('\n📈 categoryResults:')
categoryResults.forEach(category => {
console.log(`${category.name}: ${category.score}`)
})
// 6. 驗證總分一致性
console.log('\n📊 6. 驗證總分一致性...')
const totalScore = answers.reduce((sum, answer) => sum + answer.score, 0)
const maxTotalScore = answers.length * 5
const totalPercentage = Math.round((totalScore / maxTotalScore) * 100)
console.log(`資料庫總分數: ${testResult.correct_answers}`)
console.log(`計算總分數: ${totalScore}`)
console.log(`資料庫百分比: ${testResult.score}%`)
console.log(`計算百分比: ${totalPercentage}%`)
console.log(`一致性: ${testResult.correct_answers === totalScore && testResult.score === totalPercentage ? '✅ 一致' : '❌ 不一致'}`)
}
}
} catch (error) {
console.error('❌ 測試失敗:', error.message)
} finally {
console.log('\n✅ 修正後的維度分數計算測試完成')
}
}
testFixedDimensionScoring()