v2 - 검수중 (하이퍼링크 처리구문 추가)

This commit is contained in:
2025-05-19 17:50:18 +09:00
parent 2d307d77a0
commit 8e8abfd9f1
8 changed files with 136 additions and 21 deletions

View File

@@ -43,7 +43,7 @@ class XMLScorer:
return pt
# 유사한 텍스트 찾기
def find_similar_text(self, root, target_text, threshold=0.7):
def find_similar_text(self, root, chart_tree, target_text, threshold=0.7):
"""
전체 문서에서 유사한 텍스트를 찾아 반환
@@ -64,7 +64,10 @@ class XMLScorer:
'c': 'http://schemas.openxmlformats.org/drawingml/2006/chart'
}
all_text = root.xpath(f"//BODY//text() | //TEXTART/@Text | //c:chart//text()", namespaces=namespaces)
hwp_text = root.xpath(f"//BODY//text() | //TEXTART/@Text")
chart_text = chart_tree.xpath(f"//c:chart//text()", namespaces=namespaces) if chart_tree is not None else []
all_text = hwp_text + chart_text
# 유사도 비교
max_score = 0
@@ -161,7 +164,7 @@ class XMLScorer:
# search_value가 있는 경우
if search_value is not None:
# search_value를 포함하는 텍스트 찾기
similar_text = self.find_similar_text(root, search_value)
similar_text = self.find_similar_text(root, chart_tree, search_value)
xpath = xpath.replace('{searchValue}', similar_text) if xpath else ""
xpath2 = xpath2.replace('{searchValue}', similar_text) if xpath2 else ""
chart_xpath = chart_xpath.replace('{searchValue}', similar_text) if chart_xpath else ""
@@ -237,6 +240,23 @@ class XMLScorer:
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
# 1, 2페이지 모두 정답이어야 함
elif (category or "") == "PageNumber":
items = root.xpath(xpath) if xpath else []
all_match = True
for item in chain(items):
user_answer = item
if right_answer != user_answer:
all_match = False
break
if all_match:
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
else:
self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal")
# 오타 감점 부분은 미리 계산 하고, 이후 점수만 계산
elif (category or "") == "오타감점":
points = self.get_typo_score()
@@ -388,9 +408,10 @@ class XMLScorer:
if right_answer in ["견고딕", "중고딕"]:
user_answer = user_answer.replace("한양", "")
# 하나라도 다르면 바로 오답 처리
if user_answer != right_answer:
all_match = False
break # 하나라도 다르면 바로 오답 처리
break
if all_match:
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
@@ -399,18 +420,96 @@ class XMLScorer:
# 폰트 속성
elif (category or "") == "FontAttribute":
charshape = root.xpath(xpath)
if not charshape:
charshape = None
user_answer = None
else:
font_attribute = charshape[0].find(right_answer)
if font_attribute is not None:
user_answer = font_attribute.tag
else:
user_answer = None
# 하이퍼링크 처리
hyperlink_ptag = criterion.get('hyperlink_ptag', None)
has_ptag = root.xpath(hyperlink_ptag) if hyperlink_ptag else False
# hyperlink가 아닌 경우(일반적인 텍스트 일 경우)
if not has_ptag:
charshape = root.xpath(xpath)
if not charshape:
charshape = None
user_answer = None
else:
font_attribute = charshape[0].find(right_answer)
if font_attribute is not None:
user_answer = font_attribute.tag
else:
user_answer = None
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
# 하이퍼링크인 경우
elif has_ptag:
hyperlink_text = search_value.replace(" ", "")
p_elements = has_ptag
for p in p_elements:
text_list = p.xpath(".//CHAR/text()")
full_text = ''.join(text_list).replace(" ", "")
# print("full_text: ", full_text)
# 채점하고자 하는 문자열 (search_value)의 첫 문자
first_char = search_value[0]
# 수험자 답안에서 첫 문자 인덱스 위치
user_answer_first_index = full_text.find(first_char)
if user_answer_first_index != -1:
# 수험자 답안에서 첫 문자 인덱스 위치부터 search_value 길이만큼 잘라서 비교
trimmed_full_text = full_text[user_answer_first_index:]
else:
trimmed_full_text = full_text
# 두 문자열의 유사도 계산
similarity = difflib.SequenceMatcher(None, trimmed_full_text, hyperlink_text).ratio()
# 두 문자열의 유사도에 따라 하이퍼링크 확인
# 유사도가 낮은 경우 오답처리
if similarity < 0.7:
self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal")
# 유사도가 높은 경우
else:
inside_field = False
charshape_list = []
for elem in p.iter():
# 시작 지점 확인
if elem.tag == "FIELDBEGIN":
inside_field = True
elif elem.tag == "FIELDEND":
inside_field = False
elif inside_field and elem.tag == "TEXT":
charshape = elem.get("CharShape")
if charshape:
charshape_list.append(charshape)
# 하이퍼링크에 해당하는 P태그 내 존재하는 charshape ID값 모두를 비교해 해당 속성(ITALIC, BOLD, UNDERLINE) 확인
# 모든 charshape ID값이 정답과 일치하는 경우에만 점수 부여
all_attributes_match = True
if charshape_list:
for charshape_id in charshape_list:
charshape = root.xpath(f"//CHARSHAPE[@Id='{charshape_id}']")
# 속성 태그가 존재하는지 확인
font_attribute = charshape[0].find(right_answer)
if font_attribute is None:
user_answer = None
all_attributes_match = False
break
else:
user_answer = font_attribute.tag
if all_attributes_match:
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
else:
self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal")
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
# 특수문자 갯수 채점
elif (category or "") == "SpecialChar":