merge(study): 카드 그룹핑(material)

This commit is contained in:
hyungi
2026-06-07 00:41:26 +00:00
2 changed files with 31 additions and 13 deletions
+29 -13
View File
@@ -38,6 +38,7 @@ class CardEvidence(BaseModel):
class CardItem(BaseModel):
id: int
source_kind: str = "question"
format: str
cue: str
fact: str
@@ -142,19 +143,34 @@ async def list_cards(
).all()
q_meta = {r.id: (r.question_text, r.correct_choice) for r in q_rows}
# 그룹핑 (출제순서=rows 순서 유지)
groups: dict[int | None, CardQuestionGroup] = {}
order: list[int | None] = []
# 그룹핑 (출제순서=rows 순서 유지). question 카드는 출처 문제별,
# manual(직접 추가) 카드는 extra.material 별로 묶는다.
groups: dict[str, CardQuestionGroup] = {}
order: list[str] = []
for c in rows:
key = c.source_question_id
if key not in groups:
qt, cc = q_meta.get(key, (None, None)) if key is not None else (None, None)
groups[key] = CardQuestionGroup(source_question_id=key, question_text=qt, correct_choice=cc, cards=[])
order.append(key)
groups[key].cards.append(
if c.source_question_id is not None:
gkey = f"q:{c.source_question_id}"
else:
material = c.extra.get("material") if isinstance(c.extra, dict) else None
gkey = f"m:{material or '직접 추가'}"
if gkey not in groups:
if c.source_question_id is not None:
qt, cc = q_meta.get(c.source_question_id, (None, None))
groups[gkey] = CardQuestionGroup(
source_question_id=c.source_question_id, question_text=qt, correct_choice=cc, cards=[]
)
else:
material = c.extra.get("material") if isinstance(c.extra, dict) else None
groups[gkey] = CardQuestionGroup(
source_question_id=None,
question_text=(f"[자료] {material}" if material else "직접 추가 카드"),
correct_choice=None, cards=[],
)
order.append(gkey)
groups[gkey].cards.append(
CardItem(
id=c.id, format=c.format, cue=c.cue, fact=c.fact, cloze_text=c.cloze_text,
needs_review=c.needs_review, flagged_by=c.flagged_by,
id=c.id, source_kind=c.source_kind, format=c.format, cue=c.cue, fact=c.fact,
cloze_text=c.cloze_text, needs_review=c.needs_review, flagged_by=c.flagged_by,
evidence=ev_by_card.get(c.id, []),
)
)
@@ -221,8 +237,8 @@ async def update_card(
raise HTTPException(status_code=409, detail="같은 정답의 중복 카드가 이미 있습니다")
return CardItem(
id=card.id, format=card.format, cue=card.cue, fact=card.fact, cloze_text=card.cloze_text,
needs_review=card.needs_review, flagged_by=card.flagged_by, evidence=[],
id=card.id, source_kind=card.source_kind, format=card.format, cue=card.cue, fact=card.fact,
cloze_text=card.cloze_text, needs_review=card.needs_review, flagged_by=card.flagged_by, evidence=[],
)
@@ -211,6 +211,8 @@
</div>
{#if c.evidence?.length}
<div class="mt-2 text-[11px] text-dim">근거: {c.evidence[0].snippet}</div>
{:else if c.source_kind === 'manual'}
<div class="mt-2 text-[11px] text-faint">출처: 직접 추가 자료</div>
{:else}
<div class="mt-2 text-[11px] text-faint">근거: 확정 풀이(비정량 개념)</div>
{/if}