fix: score distribution chart bars + add binaryDecision backfill script
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m15s
All checks were successful
Build and Push Docker Image / build (push) Successful in 11m15s
Chart: fixed bars not rendering by using explicit h-[160px] + min-h-0 on the bar container so percentage-based heights resolve correctly. Script: one-off backfill copies the custom "Move to the Next Stage?" boolean criterion value into binaryDecision for evaluations where it's null. Run: npx tsx scripts/backfill-binary-decision.ts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
84
scripts/backfill-binary-decision.ts
Normal file
84
scripts/backfill-binary-decision.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* One-off script: backfill binaryDecision from custom boolean criterion
|
||||
* "Move to the Next Stage?" for evaluations where binaryDecision is null.
|
||||
*
|
||||
* Usage: npx tsx scripts/backfill-binary-decision.ts
|
||||
*
|
||||
* What it does:
|
||||
* 1. Finds all rounds with a boolean criterion labeled "Move to the Next Stage?"
|
||||
* 2. For evaluations in those rounds where binaryDecision IS NULL,
|
||||
* copies the boolean value from criterionScoresJson into binaryDecision
|
||||
*/
|
||||
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
type CriterionConfig = {
|
||||
id: string
|
||||
label: string
|
||||
type?: string
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Find all rounds that have evaluation config with criteria
|
||||
const rounds = await prisma.round.findMany({
|
||||
where: { roundType: 'EVALUATION' },
|
||||
select: { id: true, name: true, configJson: true },
|
||||
})
|
||||
|
||||
let totalUpdated = 0
|
||||
|
||||
for (const round of rounds) {
|
||||
const config = round.configJson as Record<string, unknown> | null
|
||||
if (!config) continue
|
||||
|
||||
const criteria = (config.criteria ?? config.evaluationCriteria ?? []) as CriterionConfig[]
|
||||
|
||||
// Find the boolean criterion for "Move to the Next Stage?"
|
||||
const boolCriterion = criteria.find(
|
||||
(c) =>
|
||||
(c.type === 'boolean') &&
|
||||
c.label?.toLowerCase().includes('move to the next stage'),
|
||||
)
|
||||
|
||||
if (!boolCriterion) continue
|
||||
|
||||
console.log(`Round "${round.name}" (${round.id}): found criterion "${boolCriterion.label}" (${boolCriterion.id})`)
|
||||
|
||||
// Find evaluations in this round where binaryDecision is null
|
||||
const evaluations = await prisma.evaluation.findMany({
|
||||
where: {
|
||||
assignment: { roundId: round.id },
|
||||
binaryDecision: null,
|
||||
status: 'SUBMITTED',
|
||||
criterionScoresJson: { not: undefined },
|
||||
},
|
||||
select: { id: true, criterionScoresJson: true },
|
||||
})
|
||||
|
||||
let updated = 0
|
||||
for (const ev of evaluations) {
|
||||
const scores = ev.criterionScoresJson as Record<string, unknown> | null
|
||||
if (!scores) continue
|
||||
|
||||
const value = scores[boolCriterion.id]
|
||||
if (typeof value !== 'boolean') continue
|
||||
|
||||
await prisma.evaluation.update({
|
||||
where: { id: ev.id },
|
||||
data: { binaryDecision: value },
|
||||
})
|
||||
updated++
|
||||
}
|
||||
|
||||
console.log(` Updated ${updated}/${evaluations.length} evaluations`)
|
||||
totalUpdated += updated
|
||||
}
|
||||
|
||||
console.log(`\nDone. Total evaluations updated: ${totalUpdated}`)
|
||||
}
|
||||
|
||||
main()
|
||||
.catch(console.error)
|
||||
.finally(() => prisma.$disconnect())
|
||||
@@ -38,13 +38,13 @@ export function ScoreDistribution({ roundId }: ScoreDistributionProps) {
|
||||
No evaluations submitted yet
|
||||
</p>
|
||||
) : (
|
||||
<div className="flex gap-1 flex-1 min-h-[120px]">
|
||||
<div className="flex gap-1 h-[160px]">
|
||||
{dist.globalDistribution.map((bucket) => {
|
||||
const heightPct = (bucket.count / maxCount) * 100
|
||||
return (
|
||||
<div key={bucket.score} className="flex-1 flex flex-col items-center gap-1 h-full">
|
||||
<div key={bucket.score} className="flex-1 flex flex-col items-center gap-1">
|
||||
<span className="text-[9px] text-muted-foreground">{bucket.count || ''}</span>
|
||||
<div className="w-full flex-1 relative">
|
||||
<div className="w-full flex-1 relative min-h-0">
|
||||
<div className={cn(
|
||||
'absolute inset-x-0 bottom-0 rounded-t transition-all',
|
||||
bucket.score <= 3 ? 'bg-red-400' :
|
||||
|
||||
Reference in New Issue
Block a user