v2 - 2504회 C형 채점 및 추가 수정
This commit is contained in:
145
diwScoring2.py
145
diwScoring2.py
@@ -164,12 +164,6 @@ class XMLScorer:
|
||||
|
||||
# search_value가 있는 경우
|
||||
if search_value is not None:
|
||||
# # 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 ""
|
||||
|
||||
if xpath or xpath2:
|
||||
similar_text = self.find_similar_text(root, search_value, xml_type="hml")
|
||||
xpath = xpath.replace('{searchValue}', similar_text) if xpath else ""
|
||||
@@ -192,22 +186,35 @@ class XMLScorer:
|
||||
'right_answer': right_answer, # 정답
|
||||
'user_answer': None, # 실제 작성 답안
|
||||
'points': 0, # 점수
|
||||
'deductions': [] # 각 기준별 감점 내역
|
||||
}
|
||||
|
||||
if (category or "") == "PageSetting":
|
||||
items = root.xpath(xpath)
|
||||
error_range = criterion.get('tolerance', 0)
|
||||
|
||||
right_answer = {
|
||||
'Top' : float(right_answer.get("Top", 0)),
|
||||
'Bottom' : float(right_answer.get("Bottom", 0)),
|
||||
'Left' : float(right_answer.get("Left", 0)),
|
||||
'Right' : float(right_answer.get("Right", 0)),
|
||||
'Header' : float(right_answer.get("Header", 0)),
|
||||
'Footer' : float(right_answer.get("Footer", 0)),
|
||||
'Gutter' : float(right_answer.get("Gutter", 0)),
|
||||
}
|
||||
right_answer = {
|
||||
k: self.convert_mm_to_pt(v)
|
||||
for k, v in right_answer.items()
|
||||
}
|
||||
|
||||
for item in items:
|
||||
user_answer = {
|
||||
'Bottom' : int(item.get("Bottom", 0)),
|
||||
'Footer' : int(item.get("Footer", 0)),
|
||||
'Gutter' : int(item.get("Gutter", 0)),
|
||||
'Header' : int(item.get("Header", 0)),
|
||||
'Left' : int(item.get("Left", 0)),
|
||||
'Right' : int(item.get("Right", 0)),
|
||||
'Top' : int(item.get("Top", 0)),
|
||||
'Top' : float(item.get("Top", 0)),
|
||||
'Bottom' : float(item.get("Bottom", 0)),
|
||||
'Left' : float(item.get("Left", 0)),
|
||||
'Right' : float(item.get("Right", 0)),
|
||||
'Header' : float(item.get("Header", 0)),
|
||||
'Footer' : float(item.get("Footer", 0)),
|
||||
'Gutter' : float(item.get("Gutter", 0)),
|
||||
}
|
||||
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range)
|
||||
@@ -274,19 +281,32 @@ class XMLScorer:
|
||||
self.partial_score += points
|
||||
scoring['points'] = points
|
||||
|
||||
# 정답이 하나인 경우
|
||||
elif (category or "") == "OneAnswer":
|
||||
# 정답이 하나 또는 테이블의 모든 값이 정답인 경우
|
||||
elif (category or "") in ["OneAnswer", "TableOneAnswer"]:
|
||||
items = root.xpath(xpath) if xpath else []
|
||||
items2 = root.xpath(xpath2) if xpath2 else []
|
||||
chart_items = chart_tree.xpath(chart_xpath, namespaces=namespaces) if chart_xpath else []
|
||||
|
||||
|
||||
require_all_match = (category == "TableOneAnswer")
|
||||
any_match = False
|
||||
all_match = True
|
||||
|
||||
for item in chain(items, items2, chart_items):
|
||||
user_answer = item
|
||||
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, points)
|
||||
|
||||
if scoring['points'] > 0:
|
||||
break
|
||||
if user_answer == right_answer:
|
||||
any_match = True
|
||||
else:
|
||||
all_match = False
|
||||
if require_all_match:
|
||||
break # 하나라도 다르면 바로 탈출
|
||||
|
||||
if require_all_match:
|
||||
score = points if all_match else 0
|
||||
else:
|
||||
score = points if any_match else 0
|
||||
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, score)
|
||||
|
||||
elif (category or "") == "DoubleAnswer":
|
||||
items1 = root.xpath(xpath) if xpath else []
|
||||
@@ -312,14 +332,14 @@ class XMLScorer:
|
||||
# 이 경우를 대비하여 tolerance를 10으로 설정 (1pt=약0.04mm 만큼의 오차 혀용)
|
||||
error_range = criterion.get('tolerance', 10)
|
||||
|
||||
# JSON 파일 value키값에 mm나 공백이 입력될 경우 제거
|
||||
# 예) "80.2 mm" >> 80.2 로 변환
|
||||
float_string = right_answer.strip().replace("mm", "")
|
||||
right_answer = self.convert_mm_to_pt(float(float_string))
|
||||
|
||||
for item in items:
|
||||
user_answer = float(item)
|
||||
|
||||
# JSON 파일 value키값에 mm나 공백이 입력될 경우 제거
|
||||
# 예) "80.2 mm" >> 80.2 로 변환
|
||||
float_string = right_answer.strip().replace("mm", "")
|
||||
right_answer = self.convert_mm_to_pt(float(float_string))
|
||||
|
||||
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range)
|
||||
|
||||
if scoring['points'] > 0:
|
||||
@@ -356,7 +376,14 @@ class XMLScorer:
|
||||
items2 = root.xpath(xpath2) if xpath2 else []
|
||||
|
||||
rgb_text = right_answer
|
||||
r, g, b = map(int, rgb_text.split(','))
|
||||
|
||||
# 정규식을 이용해 숫자만 리스트로 추출
|
||||
numbers = re.findall(r'\d+', rgb_text)
|
||||
r, g, b = map(int, numbers) if len(numbers) == 3 else None
|
||||
|
||||
# 콤마(,)로 구분된 문자열을 정수형으로 변환
|
||||
# r, g, b = map(int, rgb_text.split(','))
|
||||
|
||||
rgb_int = (b << 16) + (g << 8) + r
|
||||
|
||||
# items, items2를 순차적으로 순회
|
||||
@@ -381,58 +408,48 @@ class XMLScorer:
|
||||
break
|
||||
|
||||
# 폰트명
|
||||
elif (category or "") == "FontName":
|
||||
elif (category or "") in ["FontName", "TableFontName"]:
|
||||
charshape_list = root.xpath(xpath)
|
||||
if not charshape_list:
|
||||
user_answer = ""
|
||||
else:
|
||||
for charshape_id in charshape_list:
|
||||
font_id = root.xpath(f"//CHARSHAPE[@Id='{charshape_id}']/FONTID/@Hangul")
|
||||
font_name = root.xpath(f"//FONTFACE[@Lang='Hangul']/FONT[@Id='{font_id[0]}']/@Name")
|
||||
user_answer = font_name[0]
|
||||
|
||||
# 폰트 "견고딕"과 "중고딕"은
|
||||
# 한글프로그램 내부적으로 "한양견고딕", "한양중고딕"으로 저장되므로
|
||||
# 수험자 답변에서 "한양"을 제거
|
||||
if right_answer in ["견고딕", "중고딕"]:
|
||||
user_answer = user_answer.replace("한양", "")
|
||||
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
|
||||
|
||||
if scoring['points'] > 0:
|
||||
break
|
||||
|
||||
# 테이블 폰트명
|
||||
# 테이블 내부 모든 셀의 폰트가 정답과 일치해야 함
|
||||
elif (category or "") == "TableFontName":
|
||||
charshape_list = root.xpath(xpath)
|
||||
|
||||
|
||||
# 문자속성이 없는 경우
|
||||
if not charshape_list:
|
||||
user_answer = ""
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
|
||||
else:
|
||||
all_match = True # 모든 항목이 정답과 일치해야 함
|
||||
|
||||
require_all_match = (category == "TableFontName")
|
||||
any_match = False
|
||||
all_match = True
|
||||
|
||||
for charshape_id in charshape_list:
|
||||
font_id = root.xpath(f"//CHARSHAPE[@Id='{charshape_id}']/FONTID/@Hangul")
|
||||
if not font_id:
|
||||
all_match = False
|
||||
continue
|
||||
|
||||
font_name = root.xpath(f"//FONTFACE[@Lang='Hangul']/FONT[@Id='{font_id[0]}']/@Name")
|
||||
if not font_name:
|
||||
all_match = False
|
||||
continue
|
||||
|
||||
user_answer = font_name[0]
|
||||
|
||||
# 내부 저장된 접두어 제거
|
||||
# 접두어 제거
|
||||
if right_answer in ["견고딕", "중고딕"]:
|
||||
user_answer = user_answer.replace("한양", "")
|
||||
|
||||
# 하나라도 다르면 바로 오답 처리
|
||||
if user_answer != right_answer:
|
||||
if user_answer == right_answer:
|
||||
any_match = True
|
||||
else:
|
||||
all_match = False
|
||||
break
|
||||
if require_all_match:
|
||||
break
|
||||
|
||||
if all_match:
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal")
|
||||
if require_all_match:
|
||||
score = points if all_match else 0
|
||||
else:
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") # 오답 처리
|
||||
score = points if any_match else 0
|
||||
|
||||
self.evaluate_answer(scoring, user_answer, right_answer, score, method="equal")
|
||||
|
||||
# 폰트 속성
|
||||
elif (category or "") == "FontAttribute":
|
||||
@@ -960,8 +977,8 @@ def main():
|
||||
exam_round = '2504'
|
||||
exam_types = [
|
||||
# 'A',
|
||||
'B',
|
||||
# 'C',
|
||||
# 'B',
|
||||
'C',
|
||||
]
|
||||
test_mode = False
|
||||
# test_mode = True
|
||||
|
||||
Reference in New Issue
Block a user