"""The figures attached to a question. A question used to carry one stem image and one explanation image as two filename columns. `question_media` replaced that with rows — any number of figures, each with a role, a label the prose can refer to, a caption and an order — but only the editor's own endpoint ever read them, so the quiz player and the answer review still showed the two legacy paths. This is the one place that turns those rows into what a page renders, so the editor, the player and the review cannot disagree about what is on a question. """ from collections import defaultdict from sqlalchemy.orm import Session from app.models.media import MediaAsset from app.models.question_media import QuestionMedia def figure_json(link: QuestionMedia, asset: MediaAsset) -> dict: return { "id": link.id, "media_id": link.media_id, "role": link.role, # The label the prose refers to. Falls back to a number so a figure is # never nameless, which is what makes "see the figure" ambiguous. # An educator's label, or nothing. "Figure 1" and "Figure from question # #3360" told a learner only that an image was an image, and the second # one told them the internal path it came from as well. "label": link.label or None, "caption": link.caption or getattr(asset, "caption", None), "title": getattr(asset, "title", None), "path": getattr(asset, "path", None), "position": link.position, } def figures_for_questions(db: Session, question_ids) -> dict[int, list[dict]]: """Figures for many questions at once, keyed by question id. One query for a whole quiz rather than one per question — a 240-question exam would otherwise fan out into 240 round trips to build one page. """ ids = [qid for qid in dict.fromkeys(question_ids) if qid] if not ids: return {} rows = (db.query(QuestionMedia, MediaAsset) .join(MediaAsset, MediaAsset.id == QuestionMedia.media_id) .filter(QuestionMedia.question_id.in_(ids)) .order_by(QuestionMedia.role, QuestionMedia.position, QuestionMedia.id) .all()) out: dict[int, list[dict]] = defaultdict(list) for link, asset in rows: out[link.question_id].append(figure_json(link, asset)) return out def figures_for(db: Session, question_id: int) -> list[dict]: return figures_for_questions(db, [question_id]).get(question_id, [])