feat: side panel shows per-juror baseline and balanced contribution
Extends the ranking router's roundEvaluationScores response with per-juror grading stats (mean, stddev, count) plus the round's overall mean/stddev. The side-sheet juror rows render 'typical X.XX → contributes Y.YY' next to each Score badge whenever balanced is on, making the z-rescaling visible per individual rather than only as a project-level number. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1136,6 +1136,28 @@ export function RankingDashboard({ competitionId: _competitionId, roundId }: Ran
|
||||
</Badge>
|
||||
)}
|
||||
<Badge variant="outline">Score: {a.evaluation?.globalScore?.toFixed(1) ?? '—'}</Badge>
|
||||
{useBalanced && (() => {
|
||||
const userId = a.user?.id
|
||||
const score = a.evaluation?.globalScore
|
||||
if (!userId || score == null) return null
|
||||
const stats = evalScores?.jurorStats?.[userId]
|
||||
const overallMean = evalScores?.overallMean
|
||||
const overallStddev = evalScores?.overallStddev
|
||||
if (!stats || overallMean == null || overallStddev == null || overallStddev === 0) return null
|
||||
const z = stats.stddev > 0
|
||||
? (score - stats.mean) / stats.stddev
|
||||
: (score - overallMean) / overallStddev
|
||||
const contributesAs = overallMean + z * overallStddev
|
||||
return (
|
||||
<span
|
||||
className="text-xs text-muted-foreground"
|
||||
title={`Their typical score in this round; rescaled contribution after juror balancing`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
typical {stats.mean.toFixed(2)} → contributes {contributesAs.toFixed(2)}
|
||||
</span>
|
||||
)
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
{isExpanded && a.evaluation?.feedbackText && (
|
||||
|
||||
@@ -537,6 +537,19 @@ export const rankingRouter = router({
|
||||
}
|
||||
}
|
||||
|
||||
return { byProject, balanced }
|
||||
// Per-juror grading stats so the side panel can render each juror's
|
||||
// personal baseline and rescaled contribution.
|
||||
const jurorStats: Record<string, { mean: number; stddev: number; count: number }> = {}
|
||||
for (const [userId, s] of balanceCtx.jurorStats.entries()) {
|
||||
jurorStats[userId] = { mean: s.mean, stddev: s.stddev, count: s.count }
|
||||
}
|
||||
|
||||
return {
|
||||
byProject,
|
||||
balanced,
|
||||
jurorStats,
|
||||
overallMean: balanceCtx.overallMean,
|
||||
overallStddev: balanceCtx.overallStddev,
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user