修正總分語細項不統一的問題

This commit is contained in:
2025-09-24 18:28:24 +08:00
parent b4ee9da2bc
commit e44a94a35f
6 changed files with 65 additions and 23 deletions

View File

@@ -263,7 +263,7 @@ export async function POST(request: NextRequest) {
score: score, score: score,
max_score: maxScore, max_score: maxScore,
weight: criteriaItem.weight, weight: criteriaItem.weight,
weighted_score: (score / maxScore) * criteriaItem.weight, weighted_score: (score / maxScore) * (criteriaItem.weight / 100),
percentage: (score / maxScore) * 100 percentage: (score / maxScore) * 100
}; };
@@ -274,7 +274,7 @@ export async function POST(request: NextRequest) {
score: score, score: score,
max_score: maxScore, max_score: maxScore,
weight: criteriaItem.weight, weight: criteriaItem.weight,
weighted_score: (score / maxScore) * criteriaItem.weight, weighted_score: (score / maxScore) * (criteriaItem.weight / 100),
percentage: (score / maxScore) * 100 percentage: (score / maxScore) * 100
}); });

View File

@@ -85,7 +85,7 @@ export async function GET(
overview: { overview: {
excellentItems: evaluationWithDetails.excellent_items || 0, excellentItems: evaluationWithDetails.excellent_items || 0,
improvementItems: evaluationWithDetails.improvement_items || 0, improvementItems: evaluationWithDetails.improvement_items || 0,
overallPerformance: Number(evaluationWithDetails.overall_score) || 0 overallPerformance: Math.round(Number(evaluationWithDetails.overall_score) || 0)
}, },
improvementSuggestions: { improvementSuggestions: {
overallSuggestions: feedbackByType.overall[0]?.content || '無詳細分析', overallSuggestions: feedbackByType.overall[0]?.content || '無詳細分析',

View File

@@ -109,7 +109,7 @@ export async function GET(
overview: { overview: {
excellentItems: evaluationWithDetails.excellent_items || 0, excellentItems: evaluationWithDetails.excellent_items || 0,
improvementItems: evaluationWithDetails.improvement_items || 0, improvementItems: evaluationWithDetails.improvement_items || 0,
overallPerformance: Number(evaluationWithDetails.overall_score) || 0 overallPerformance: Math.round(Number(evaluationWithDetails.overall_score) || 0)
}, },
detailedAnalysis: { detailedAnalysis: {
summary: feedbackByType.overall[0]?.content || '無詳細分析', summary: feedbackByType.overall[0]?.content || '無詳細分析',

View File

@@ -103,7 +103,7 @@ const calculateMockOverview = (criteria: any[]) => {
const improvementItems = criteria.filter(item => item.score < averageScore).length; const improvementItems = criteria.filter(item => item.score < averageScore).length;
// 整體表現:基於權重的加權平均分數 // 整體表現:基於權重的加權平均分數
const overallPerformance = Math.round(criteria.reduce((sum, item) => sum + (item.score / item.maxScore) * item.weight, 0)); const overallPerformance = Math.round(criteria.reduce((sum, item) => sum + (item.score / item.maxScore) * (item.weight / 100), 0));
return { return {
excellentItems, excellentItems,
@@ -254,7 +254,7 @@ export default function ResultsContent() {
const improvementItems = criteria.filter(item => item.score < averageScore).length; const improvementItems = criteria.filter(item => item.score < averageScore).length;
// 整體表現:基於權重的加權平均分數 // 整體表現:基於權重的加權平均分數
const overallPerformance = Math.round(criteria.reduce((sum, item) => sum + (item.score / item.maxScore) * item.weight, 0)); const overallPerformance = Math.round(criteria.reduce((sum, item) => sum + (item.score / item.maxScore) * (item.weight / 100), 0) * 10) / 10;
return { return {
excellentItems, excellentItems,
@@ -263,9 +263,24 @@ export default function ResultsContent() {
}; };
}; };
// 重新計算基於權重的總分
const calculateWeightedTotalScore = (criteria: any[]): number => {
if (!criteria || criteria.length === 0) return 0;
const totalScore = criteria.reduce((sum, item) => {
const weightedScore = (item.score / item.maxScore) * (item.weight / 100);
return sum + weightedScore;
}, 0);
// 將小數轉換為100分制的分數保留一位小數
return Math.round(totalScore * 100 * 10) / 10; // 保留一位小數
};
// 確保所有必要的數據結構存在 // 確保所有必要的數據結構存在
const safeResults = { const safeResults = {
...results, ...results,
// 重新計算總分
overallScore: calculateWeightedTotalScore(results.criteria || []),
overview: results.overview || calculateOverview(results.criteria || []), overview: results.overview || calculateOverview(results.criteria || []),
chartData: results.chartData || { chartData: results.chartData || {
barChart: [], barChart: [],

View File

@@ -145,7 +145,17 @@ ${criteriaList}
**評分要求:** **評分要求:**
1. 請對每個評分項目給出 0 到滿分的分數,要敢於給出極高分(9-10分)和極低分(1-3分) 1. 請對每個評分項目給出 0 到滿分的分數,要敢於給出極高分(9-10分)和極低分(1-3分)
2. 為每個項目提供具體的評分理由、優點和改進建議 2. 為每個項目提供具體的評分理由、優點和改進建議
3. 計算總分(各項目分數 × 權重比例) 3. **重要:計算總分時,請嚴格按照以下步驟:**
- 步驟1計算每個項目的加權分數 = (該項目得分 ÷ 該項目滿分) × 該項目權重百分比
- 步驟2將所有項目的加權分數相加得到總分
- 步驟3檢查計算結果是否正確
- **計算範例:**
* 應用實務性8/10 × 30% = 0.8 × 30 = 24分
* 創新性6/10 × 15% = 0.6 × 15 = 9分
* 成效與效益9/10 × 25% = 0.9 × 25 = 22.5分
* 擴散與可複用性7/10 × 20% = 0.7 × 20 = 14分
* 簡報與表達8/10 × 10% = 0.8 × 10 = 8分
* **總分 = 24 + 9 + 22.5 + 14 + 8 = 77.5分**
4. 提供整體評價和建議 4. 提供整體評價和建議
5. 分析優秀項目和待改進項目的數量 5. 分析優秀項目和待改進項目的數量
6. 給出等級評比 (S、A+、A、A-、B+、B、B-、C、D) 6. 給出等級評比 (S、A+、A、A-、B+、B、B-、C、D)
@@ -156,7 +166,7 @@ ${criteriaList}
**回應格式 (請嚴格按照以下 JSON 格式回應):** **回應格式 (請嚴格按照以下 JSON 格式回應):**
{ {
"projectTitle": "專案標題", "projectTitle": "專案標題",
"overallScore": 總分數字, "overallScore": 總分數字必須是根據加權公式計算的正確總分請仔細計算每個項目的加權分數後相加例如77.5,
"totalPossible": 100, "totalPossible": 100,
"grade": "等級評比", "grade": "等級評比",
"performanceStatus": "表現狀態", "performanceStatus": "表現狀態",
@@ -239,6 +249,12 @@ ${criteriaList}
} }
} }
**重要提醒:在回應前,請務必檢查以下計算:**
1. 列出每個項目的得分和權重
2. 計算每個項目的加權分數:(得分÷滿分) × 權重百分比
3. 將所有加權分數相加得到總分
4. 確認總分是否正確
請確保回應是有效的 JSON 格式,不要包含任何其他文字。 請確保回應是有效的 JSON 格式,不要包含任何其他文字。
`.trim(); `.trim();
} }
@@ -308,8 +324,8 @@ ${criteriaList}
console.log(' 優秀項目 (≥' + averageScore + '):', excellentItems); console.log(' 優秀項目 (≥' + averageScore + '):', excellentItems);
console.log(' 待改進項目 (<' + averageScore + '):', improvementItems); console.log(' 待改進項目 (<' + averageScore + '):', improvementItems);
// 整體表現:基於權重的加權平均分數 // 整體表現:基於權重的加權平均分數(百分比)
const overallPerformance = Math.round(criteria.reduce((sum, item) => sum + (item.score / item.maxScore) * item.weight, 0)); const overallPerformance = Math.round(criteria.reduce((sum, item) => sum + (item.score / item.maxScore) * (item.weight / 100), 0) * 100);
return { return {
excellentItems, excellentItems,
@@ -331,7 +347,7 @@ ${criteriaList}
})), })),
pieChart: criteria.map(item => ({ pieChart: criteria.map(item => ({
name: item.name, name: item.name,
value: item.weightedScore || (item.score / item.maxScore) * item.weight, value: item.weightedScore || (item.score / item.maxScore) * (item.weight / 100),
weight: item.weight weight: item.weight
})), })),
radarChart: criteria.map(item => ({ radarChart: criteria.map(item => ({
@@ -387,14 +403,25 @@ ${criteriaList}
private static convertToProjectEvaluation(parsed: any, criteria: CriteriaItem[]): ProjectEvaluation { private static convertToProjectEvaluation(parsed: any, criteria: CriteriaItem[]): ProjectEvaluation {
console.log('🔄 轉換完整格式回應...'); console.log('🔄 轉換完整格式回應...');
// 計算總分 // 計算總分 - 總是重新計算,不直接使用 AI 的 overallScore
let totalScore = 0; let totalScore = 0;
if (parsed.overallScore) { if (parsed.criteria && Array.isArray(parsed.criteria)) {
totalScore = Number(parsed.overallScore); // 使用權重重新計算總分
} else if (parsed.criteria && Array.isArray(parsed.criteria)) {
totalScore = parsed.criteria.reduce((sum: number, item: any) => { totalScore = parsed.criteria.reduce((sum: number, item: any) => {
return sum + (Number(item.weightedScore) || 0); const score = Number(item.score) || 0;
const maxScore = Number(item.maxScore) || 10;
const weight = Number(item.weight) || 0;
const weightedScore = (score / maxScore) * (weight / 100);
console.log(` ${item.name}: ${score}/${maxScore} × ${weight}% = ${weightedScore.toFixed(2)}`);
return sum + weightedScore;
}, 0); }, 0);
// 轉換為 100 分制
totalScore = totalScore * 100;
console.log(`📊 重新計算的總分: ${totalScore.toFixed(1)}/100`);
} else if (parsed.overallScore) {
// 如果沒有 criteria 數據,才使用 AI 的 overallScore
totalScore = Number(parsed.overallScore);
console.log(`📊 使用 AI 的總分: ${totalScore}/100`);
} }
// 轉換評分結果 // 轉換評分結果
@@ -410,7 +437,7 @@ ${criteriaList}
return { return {
projectTitle: parsed.projectTitle || '', projectTitle: parsed.projectTitle || '',
projectDescription: '', projectDescription: '',
totalScore: Math.round(totalScore * 100) / 100, totalScore: Math.round(totalScore * 10) / 10, // 保留一位小數100分制
maxTotalScore: 100, maxTotalScore: 100,
results, results,
overallFeedback: parsed.detailedAnalysis?.summary || parsed.overallFeedback || '整體評價', overallFeedback: parsed.detailedAnalysis?.summary || parsed.overallFeedback || '整體評價',
@@ -570,7 +597,7 @@ ${criteriaList}
totalScore = results.reduce((sum, result) => { totalScore = results.reduce((sum, result) => {
const criteriaItem = criteria.find(c => c.id === result.criteriaId); const criteriaItem = criteria.find(c => c.id === result.criteriaId);
const weight = criteriaItem ? criteriaItem.weight : 0; const weight = criteriaItem ? criteriaItem.weight : 0;
const weightedScore = (result.score / result.maxScore) * weight; const weightedScore = (result.score / result.maxScore) * (weight / 100);
console.log(` ${result.criteriaName}: ${result.score}/${result.maxScore} × ${weight}% = ${weightedScore.toFixed(2)}`); console.log(` ${result.criteriaName}: ${result.score}/${result.maxScore} × ${weight}% = ${weightedScore.toFixed(2)}`);
return sum + weightedScore; return sum + weightedScore;
}, 0); }, 0);
@@ -587,8 +614,8 @@ ${criteriaList}
return { return {
projectTitle: '', projectTitle: '',
projectDescription: '', projectDescription: '',
totalScore: Math.round(totalScore * 100) / 100, // 四捨五入到小數點後 totalScore: Math.round(totalScore * 10) / 10, // 四捨五入到小數點後
maxTotalScore: Math.round(maxTotalScore * 100) / 100, maxTotalScore: Math.round(maxTotalScore * 10) / 10,
results, results,
overallFeedback: parsed.overallFeedback || '基於資料庫評分標準的整體評價' overallFeedback: parsed.overallFeedback || '基於資料庫評分標準的整體評價'
}; };
@@ -621,7 +648,7 @@ ${criteriaList}
totalScore = results.reduce((sum, result) => { totalScore = results.reduce((sum, result) => {
const criteriaItem = criteria.find(c => c.id === result.criteriaId); const criteriaItem = criteria.find(c => c.id === result.criteriaId);
const weight = criteriaItem ? criteriaItem.weight : 0; const weight = criteriaItem ? criteriaItem.weight : 0;
return sum + ((result.score / result.maxScore) * weight); return sum + ((result.score / result.maxScore) * (weight / 100));
}, 0); }, 0);
} else { } else {
const rawTotal = results.reduce((sum, result) => sum + result.score, 0); const rawTotal = results.reduce((sum, result) => sum + result.score, 0);
@@ -632,8 +659,8 @@ ${criteriaList}
return { return {
projectTitle: '', projectTitle: '',
projectDescription: '', projectDescription: '',
totalScore: Math.round(totalScore * 100) / 100, totalScore: Math.round(totalScore * 10) / 10, // 四捨五入到小數點後一位
maxTotalScore: Math.round(maxTotalScore * 100) / 100, maxTotalScore: Math.round(maxTotalScore * 10) / 10,
results, results,
overallFeedback: '由於技術問題,無法完成完整的 AI 分析。建議檢查文件格式或重新上傳。' overallFeedback: '由於技術問題,無法完成完整的 AI 分析。建議檢查文件格式或重新上傳。'
}; };

Binary file not shown.