Created
July 11, 2025 03:00
-
-
Save sigmadream/ef67d427c0ee0ea452b35f6fae20a0ad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Annotated, List, Dict, Any | |
from fastapi import APIRouter, Depends, status, HTTPException | |
from sqlmodel import Session, select | |
from .solve import path_getter, dir_maker | |
from ..database import get_db | |
from ..models import ( | |
GichulQna, | |
GichulSet, | |
GichulSetGrade, | |
GichulSetInning, | |
GichulSetType, | |
GichulSubject, | |
) | |
from pathlib import Path | |
from collections import defaultdict | |
import os, re, random | |
from dotenv import load_dotenv | |
load_dotenv() | |
router = APIRouter(prefix="/cbt", tags=["Randomly Mixed Questions"]) | |
base_path_str = os.getenv("BASE_PATH") | |
if base_path_str is None: | |
raise ValueError("BASE_PATH not set") | |
base_path = Path(base_path_str) | |
# 상수 정의 | |
QUESTIONS_PER_SUBJECT = 25 | |
def cbt_imgpath_getter(exam_set: GichulSet) -> str: | |
directory = dir_maker( | |
year=str(exam_set.year), | |
license=exam_set.type, | |
level=exam_set.grade, | |
round=exam_set.inning | |
) | |
return directory | |
# 중복 문제 제거 및 과목 분류 | |
def remove_duplicate_questions(sets: List[GichulSet]) -> Dict[GichulSubject, List[GichulQna]]: | |
subject_questions = defaultdict(list) | |
for exam_set in sets: | |
for qna in exam_set.qnas: | |
if qna.questionstr and qna.ex1str: | |
joined_text = " ".join([qna.questionstr, qna.ex1str]) | |
if joined_text not in [existing_qna.questionstr + " " + existing_qna.ex1str | |
for existing_qna in subject_questions[qna.subject]]: | |
subject_questions[qna.subject].append(qna) | |
return subject_questions | |
# 각 기출문제 세트별 이미지 경로 | |
def create_image_path_dict(sets: List[GichulSet]) -> Dict[int, Dict[str, str]]: | |
path_dict = {} | |
for exam_set in sets: | |
directory = cbt_imgpath_getter(exam_set) | |
path_dict[exam_set.id] = path_getter(directory) | |
return path_dict | |
# 문제 선택 | |
def select_random_questions_by_subject( | |
subject_questions: Dict[GichulSubject, List[GichulQna]] | |
) -> Dict[GichulSubject, List[GichulQna]]: | |
random_questions = {} | |
for subject, questions in subject_questions.items(): | |
if len(questions) >= QUESTIONS_PER_SUBJECT: | |
random_questions[subject] = random.sample(questions, QUESTIONS_PER_SUBJECT) | |
else: | |
random_questions[subject] = questions | |
return random_questions | |
# 문제에 이미지 경로 정보를 추가합니다. | |
def add_image_paths_to_questions( | |
questions_dict: Dict[GichulSubject, List[GichulQna]], | |
path_dict: Dict[int, Dict[str, str]] | |
) -> Dict[str, List[Dict[str, Any]]]: | |
result = {} | |
pic_marker_reg = re.compile(r"@(\w+)") | |
for subject, questions in questions_dict.items(): | |
qnas_as_dicts = [qna.model_dump() for qna in questions] | |
for qna_dict in qnas_as_dicts: | |
full_text = " ".join( | |
qna_dict.get(key, " ") | |
for key in ["questionstr", "ex1str", "ex2str", "ex3str", "ex4str"] | |
) | |
found_pics = pic_marker_reg.findall(full_text) | |
if found_pics: | |
gichulset_id = qna_dict["gichulset_id"] | |
if gichulset_id in path_dict: | |
img_paths = [ | |
path_dict[gichulset_id][pic_name] | |
for pic_name in found_pics | |
if pic_name in path_dict[gichulset_id] | |
] | |
qna_dict["imgPaths"] = img_paths | |
result[subject] = qnas_as_dicts | |
return result | |
@router.get("/") | |
def get_one_random_qna_set( | |
license: GichulSetType, | |
level: GichulSetGrade, | |
db: Annotated[Session, Depends(get_db)], | |
) -> Dict[str, List[Dict[str, Any]]]: | |
try: | |
# 1. 데이터베이스에서 기출문제 세트 조회 | |
sets = db.exec( | |
select(GichulSet).where( | |
GichulSet.type == license, | |
GichulSet.grade == level | |
) | |
).all() | |
if not sets: | |
raise HTTPException( | |
status_code=status.HTTP_404_NOT_FOUND, | |
detail=f"해당 조건의 기출문제 세트를 찾을 수 없습니다: {license.value}, {level.value}급" | |
) | |
# 2. 중복 제거 및 과목별 분류 | |
subject_questions = remove_duplicate_questions(sets) | |
# 3. 이미지 경로 딕셔너리 생성 | |
path_dict = create_image_path_dict(sets) | |
# 4. 과목별 랜덤 문제 선택 | |
random_questions = select_random_questions_by_subject(subject_questions) | |
# 5. 이미지 경로 정보 추가 | |
result = add_image_paths_to_questions(random_questions, path_dict) | |
return result | |
except HTTPException: | |
raise | |
except Exception as e: | |
print(f"Error in get_one_random_qna_set: {e}") | |
raise HTTPException( | |
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
detail="문제 세트 생성 중 오류가 발생했습니다." | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment