Spaces:
Running
Running
File size: 1,977 Bytes
b324c71 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | """
Re-scores a Business Strength Archetype submission on the server, so what we
store never depends on numbers the browser sent. Mirrors lib/bsa/score.ts; the
question bank comes from questions.json, built by scripts/bsa/build_content.py.
"""
import json
import math
from pathlib import Path
_DATA = json.loads((Path(__file__).resolve().parent / "questions.json").read_text(encoding="utf-8"))
ORDER: list[str] = _DATA["order"]
STAGES: list[str] = _DATA["stages"]
AGES: list[str] = _DATA["ages"]
QUESTIONS: dict[int, dict] = {q["id"]: q for q in _DATA["questions"]}
def percentages(raw: dict[str, int]) -> dict[str, int]:
"""Whole percentages that add up to 100 (largest remainder method)."""
total = sum(raw.values()) or 1
exact = [raw[d] / total * 100 for d in ORDER]
pct = [math.floor(e) for e in exact]
order = sorted(range(len(ORDER)), key=lambda i: (-(exact[i] - pct[i]), i))
for i in order[: 100 - sum(pct)]:
pct[i] += 1
return dict(zip(ORDER, pct))
def score(answers: dict[int, str]) -> dict:
"""answers: question id → strength picked. Raises ValueError if any answer is impossible."""
if set(answers) != set(QUESTIONS):
raise ValueError(f"Expected answers to all {len(QUESTIONS)} questions.")
raw = {d: 0 for d in ORDER}
fit = {d: 0 for d in ORDER}
for qid, dim in answers.items():
q = QUESTIONS[qid]
if dim not in q["dims"]:
raise ValueError(f"Question {qid} has no option for {dim}.")
raw[dim] += 1
if dim == q["naturalFit"]:
fit[dim] += 1
ranked = sorted(ORDER, key=lambda d: (-raw[d], -fit[d], ORDER.index(d)))
primary, secondary = ranked[0], ranked[1]
pair = sorted([primary, secondary], key=ORDER.index)
return {
"raw": raw,
"pct": percentages(raw),
"primary": primary,
"secondary": secondary,
"lowest": [ranked[6], ranked[5]],
"blendKey": f"{pair[0]}-{pair[1]}",
}
|