Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions frontend/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,21 @@ function updateStatistics(subjects) {
return;
}

const scores = subjects.map(subject => subject.scoreValue);
const highest = Math.max(...scores);

// 計算加權平均
// 計算最高分與加權平均,合併迴圈以減少陣列分配與迭代,並避免 Math.max 展開大陣列時可能發生的 Stack Overflow
let highest = -Infinity;
let totalWeightedScore = 0;
let totalWeight = 0;

subjects.forEach(subject => {
for (let i = 0; i < subjects.length; i++) {
const subject = subjects[i];
const score = subject.scoreValue;

if (score > highest) highest = score;

const weight = getSubjectWeight(subject.SubjectName);
totalWeightedScore += score * weight;
totalWeight += weight;
});
}
Comment on lines +138 to +147

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a for...of loop would improve readability while maintaining the performance benefits of a single pass. Additionally, replacing the if condition with highest = Math.max(highest, score) is more idiomatic and ensures consistent NaN handling. If any scoreValue is NaN, highest will correctly become NaN, matching the behavior of weightedAvg and the original implementation (which used Math.max(...scores)).

    for (const subject of subjects) {
        const score = subject.scoreValue;
        highest = Math.max(highest, score);

        const weight = getSubjectWeight(subject.SubjectName);
        totalWeightedScore += score * weight;
        totalWeight += weight;
    }

Comment on lines +133 to +147

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scoreValue can be NaN (see getNumericScore() fallback path), and the new loop can leave highest as -Infinity when all scores are non-finite, which then renders -Infinity in the UI. Also, a single NaN score will propagate totalWeightedScore to NaN and make weightedAvg.toFixed(1) show NaN. Consider skipping non-finite scores (and their weights) when computing highest/average, and rendering '--' (or 0) when no valid numeric scores exist.

Copilot uses AI. Check for mistakes.

const weightedAvg = totalWeight > 0 ? totalWeightedScore / totalWeight : 0;

Expand Down
Loading