1. 2504회 정시 채점자료 업데이트
2. "■ 행사안내 ■" 특수문자 제외하고 검색 적용 3. 문서 내 하이퍼링크 텍스트 존재 할 경우 해당 문자열 처리 방법 추가
This commit is contained in:
121
diwScoring.py
121
diwScoring.py
@@ -35,7 +35,59 @@ class XMLScorer:
|
||||
second_xpath = args[1]
|
||||
points = args[2]
|
||||
category = args[3]
|
||||
right_answer = args[4]
|
||||
|
||||
if "Hyperlink" in category:
|
||||
is_hyperlink = self.scoring_criteria["1"]["17"]["hyperlink"]
|
||||
hyperlink_xpath = self.scoring_criteria["1"]["17"]["hyperlink_xpath"]
|
||||
right_text = self.scoring_criteria["1"]["17"]["searchValue"].replace(" ","")
|
||||
try:
|
||||
p_elements = root.xpath(is_hyperlink)
|
||||
|
||||
for p in p_elements:
|
||||
text_list = p.xpath(".//CHAR/text()")
|
||||
full_text = ''.join(text_list).replace(" ", "")
|
||||
# right_text의 첫 문자
|
||||
first_char = right_text[0]
|
||||
# full_text에서 첫 문자 위치 찾기
|
||||
index = full_text.find(first_char)
|
||||
|
||||
if index != -1:
|
||||
trimmed_full_text = full_text[index:]
|
||||
else:
|
||||
trimmed_full_text = full_text # 일치 문자 없으면 원본 그대로
|
||||
|
||||
similarity = difflib.SequenceMatcher(None, trimmed_full_text, right_text).ratio()
|
||||
# 두 문자열이 같을 경우만 하이퍼링크 확인
|
||||
if similarity >= 0.7:
|
||||
inside_field = False
|
||||
charshape_values = []
|
||||
|
||||
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_values.append(charshape)
|
||||
|
||||
# 하이퍼링크에 해당하는 P태그 내 존재하는 charshape ID값 모두를 비교해 해당 속성(ITALIC, BOLD, UNDERLINE) 확인
|
||||
if charshape_values:
|
||||
for charshape in charshape_values:
|
||||
result = root.xpath(hyperlink_xpath.replace('{charshape_id}', charshape))
|
||||
# 해당 속성이 하나라도 적용되어있지 않으면 False 반환
|
||||
if not result:
|
||||
return result
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
except ET.XPathEvalError as e:
|
||||
return None
|
||||
|
||||
if ("특수문자" in category) and (second_xpath is not None):
|
||||
try:
|
||||
result = root.xpath(first_xpath)
|
||||
@@ -51,13 +103,23 @@ class XMLScorer:
|
||||
|
||||
except ET.XPathEvalError as e:
|
||||
return None
|
||||
|
||||
|
||||
# xpath2가 있는 경우
|
||||
elif second_xpath is not None:
|
||||
try:
|
||||
result1 = root.xpath(first_xpath)
|
||||
result2 = root.xpath(second_xpath)
|
||||
if (type(result1) is list and len(result1) == 0) and (type(result2) is list and len(result2) == 0):
|
||||
return None
|
||||
|
||||
# xpath1과 xpath2의 결과값이 모두 리스트인 경우
|
||||
# 두 결과값 중 정답이 포함된 리스트를 반환
|
||||
if type(result1) is list and type(result2) is list:
|
||||
if right_answer in result1:
|
||||
return result1
|
||||
elif right_answer in result2:
|
||||
return result2
|
||||
|
||||
return result1 if result1 else result2
|
||||
|
||||
except ET.XPathEvalError as e:
|
||||
@@ -99,11 +161,15 @@ class XMLScorer:
|
||||
# all_text.append(root.xpath(f"//TEXTART/@text"))
|
||||
|
||||
namespaces = {
|
||||
|
||||
'a': 'http://schemas.openxmlformats.org/drawingml/2006/main',
|
||||
'c': 'http://schemas.openxmlformats.org/drawingml/2006/chart'
|
||||
}
|
||||
|
||||
all_text = root.xpath(f"//BODY//text() | //TEXTART/@Text | //c:chart//text()", namespaces=namespaces)
|
||||
if type(root) is str:
|
||||
all_text = root
|
||||
else:
|
||||
all_text = root.xpath(f"//BODY//text() | //TEXTART/@Text | //c:chart//text()", namespaces=namespaces)
|
||||
|
||||
# 유사도 비교
|
||||
max_score = 0
|
||||
@@ -163,39 +229,7 @@ class XMLScorer:
|
||||
category = criterion['category'] if 'category' in criterion else None
|
||||
item = criterion['item']
|
||||
similar_text = None
|
||||
|
||||
# if "pageSetting" in (format or ""):
|
||||
# results = root.xpath("//PAGEMARGIN")
|
||||
# matched = False
|
||||
|
||||
# for i, user_answer in enumerate(results):
|
||||
# bottom = int(user_answer.get("Bottom"), 0)
|
||||
# footer = int(user_answer.get("Footer"), 0)
|
||||
# gutter = int(user_answer.get("Gutter"), 0)
|
||||
# header = int(user_answer.get("Header"), 0)
|
||||
# left = int(user_answer.get("Left"), 0)
|
||||
# right = int(user_answer.get("Right"), 0)
|
||||
# top = int(user_answer.get("Top"), 0)
|
||||
# error_range = 1
|
||||
|
||||
# if abs(right_answer['Bottom'] - bottom) <= error_range and \
|
||||
# abs(right_answer['Footer'] - footer) <= error_range and \
|
||||
# abs(right_answer['Gutter'] - gutter) <= error_range and \
|
||||
# abs(right_answer['Header'] - header) <= error_range and \
|
||||
# abs(right_answer['Left'] - left) <= error_range and \
|
||||
# abs(right_answer['Right'] - right) <= error_range and \
|
||||
# abs(right_answer['Top'] - top) <= error_range:
|
||||
# matched = True
|
||||
|
||||
# total_score += points
|
||||
# partial_score += points
|
||||
# scoring['points'] = points
|
||||
# break
|
||||
|
||||
# if not matched:
|
||||
# scoring['points'] = 0
|
||||
|
||||
|
||||
# chart xml 파일에서 채점하는 경우
|
||||
if "chart_xml" in category:
|
||||
if search_value is not None:
|
||||
@@ -216,7 +250,7 @@ class XMLScorer:
|
||||
else:
|
||||
xpath = xpath.replace('{searchValue}', similar_text)
|
||||
|
||||
result = self.query_xml(root, xpath, xpath2, points, category)
|
||||
result = self.query_xml(root, xpath, xpath2, points, category, right_answer)
|
||||
|
||||
# [ boolean 타입 ]
|
||||
# 1. 이텔릭체, 굵게, 밑줄 등 효과가 적용 여부에 따라
|
||||
@@ -349,8 +383,9 @@ class XMLScorer:
|
||||
correct_input_text = [re.sub(r'\d+\.\s*|-', '', text) for text in correct_input_text]
|
||||
|
||||
try :
|
||||
xpath = self.scoring_criteria["2-29"]['path'].split("'")[1]
|
||||
ignore_word = xpath.split("'")[1]
|
||||
# xpath = self.scoring_criteria["2"]["29"]['path'].split("'")[1]
|
||||
# ignore_word = xpath.split("'")[1]
|
||||
ignore_word = self.scoring_criteria["2"]["29"]["ignoreWord"]
|
||||
# 특정 단어 제거
|
||||
# 오타와 누락의 경우만 판단하면 정상작동하지만
|
||||
# 추가 된 단어의 경우를 채점기준에 추가하면 정확하게 채점 되지 않을 수 있음
|
||||
@@ -561,20 +596,22 @@ def main():
|
||||
|
||||
# 시험회차 및 유형
|
||||
exam_round = '2504_3'
|
||||
|
||||
# 250429기준 없는 시험 형식(A,B,C..)은 주석처리 하지 않으면 오류 발생
|
||||
exam_types = [
|
||||
# 'A',
|
||||
'B',
|
||||
# 'B',
|
||||
'C',
|
||||
]
|
||||
test_mode = False
|
||||
# test_mode = True
|
||||
# test_mode = False
|
||||
test_mode = True
|
||||
|
||||
output_excel_paths = []
|
||||
for exam_type in exam_types:
|
||||
|
||||
# JSON 채점기준표 파일 (예시:DIW_2503A.json)
|
||||
scoring_criteria_path = f'./DIW_{exam_round}.json'
|
||||
# scoring_criteria_path = f'./DIW_{exam_round}{exam_type}.json'
|
||||
# scoring_criteria_path = f'./DIW_{exam_round}.json'
|
||||
scoring_criteria_path = f'./DIW_{exam_round}{exam_type}.json'
|
||||
|
||||
# xml(hml)파일 디렉토리 경로 (예시:./output/A/DIW)
|
||||
# xml_directory = f'./output/{exam_type}/{"TEST" if test_mode else "DIW"}'
|
||||
|
||||
Reference in New Issue
Block a user