55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
"""Likert scale scoring storage and aggregation."""
|
|
|
|
from typing import Dict, List
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.models import Result
|
|
|
|
|
|
def save_likert_score(db: Session, run_id: str, score: int) -> Result:
|
|
if not 1 <= score <= 5:
|
|
raise ValueError("Likert score must be between 1 and 5")
|
|
result = db.query(Result).filter_by(run_id=run_id).first()
|
|
if not result:
|
|
raise ValueError(f"Result not found for run {run_id}")
|
|
result.likert_score = score
|
|
db.commit()
|
|
db.refresh(result)
|
|
return result
|
|
|
|
|
|
def aggregate_likert_by_model_and_level(db: Session) -> Dict[str, Dict[str, Dict[str, float]]]:
|
|
"""Aggregate Likert scores by model_id and level.
|
|
|
|
Returns mean and frequency distribution per (model, level).
|
|
"""
|
|
rows = (
|
|
db.query(Result, ExperimentRun)
|
|
.join(ExperimentRun, Result.run_id == ExperimentRun.id)
|
|
.all()
|
|
)
|
|
|
|
grouped: Dict[str, Dict[str, List[int]]] = {}
|
|
for result, run in rows:
|
|
if result.likert_score is None:
|
|
continue
|
|
key_model = run.model_id
|
|
key_level = run.template_version.template.level
|
|
grouped.setdefault(key_model, {}).setdefault(key_level, []).append(result.likert_score)
|
|
|
|
output = {}
|
|
for model, levels in grouped.items():
|
|
output[model] = {}
|
|
for level, scores in levels.items():
|
|
total = len(scores)
|
|
output[model][level] = {
|
|
"mean": round(sum(scores) / total, 2) if total else 0.0,
|
|
"count": total,
|
|
"distribution": {i: scores.count(i) for i in range(1, 6)},
|
|
}
|
|
return output
|
|
|
|
|
|
from app.models import ExperimentRun # noqa: E402
|