오타점수/부분합 엑셀 시트에 적용

This commit is contained in:
devdra9
2025-01-20 17:56:46 +09:00
parent d69a2a331e
commit e59698205f
4 changed files with 65 additions and 31 deletions

View File

@@ -15,6 +15,12 @@ class XMLScorer:
def __init__(self, scoring_criteria_path):
# 채점 기준 로드
self.scoring_criteria = self._load_scoring_criteria(scoring_criteria_path)
def set_typo_score(self, score):
self.typo_score = score
def get_typo_score(self):
return self.typo_score
# 채점 기준파일 로드(JSON 파일)
def _load_scoring_criteria(self, file_path):
@@ -37,9 +43,7 @@ class XMLScorer:
return result
else:
return result
# result = root.xpath(second_xpath)
# print(f'result : {result}')
# return result
except ET.XPathEvalError as e:
return None
else:
@@ -141,6 +145,7 @@ class XMLScorer:
previous_first_digit = first_digit
id = criterion_id
xpath = criterion['path']
xpath2 = criterion['path2']
search_value = criterion['searchValue']
@@ -190,16 +195,19 @@ class XMLScorer:
actual_answer = int(result[0])
else:
actual_answer = result[0]
if "오타감점" in category:
points = self.get_typo_score()
scoring = {
'id': id,
'category': category, # 채점 분류
'item': item, # 채점 항목
'right_answer': right_answer, # 정답
'actual_answer': actual_answer, # 실제 작성 답안
'points': 0,
'points': points,
'deductions': [] # 각 기준별 감점 내역
}
scoring['points'] = points
# 점수 차감 조건
# 1. 정답이 실수형으로 반환받은 경우는 채점항목의 부분점수 합산 결과이므로
@@ -210,8 +218,8 @@ class XMLScorer:
scoring['points'] = actual_answer
elif type(actual_answer) is int:
# 오차범위 5 이상이면 감점
if abs(actual_answer - right_answer) > 5:
# 오차범위 3 이상이면 감점
if abs(actual_answer - right_answer) > 3:
scoring['points'] -= points
else:
# right_answer(JSON파일 내 valuer값) null일 경우 점수감점 없이 진행
@@ -244,8 +252,6 @@ class XMLScorer:
}
def binary_to_chartxml(self, xml_path):
print(f'binary_to_chartxml {xml_path}')
tree = ET.parse(xml_path)
root = tree.getroot()
@@ -339,24 +345,25 @@ class XMLScorer:
# result_diff 배열의 길이를 맨 앞에 저장
temp = 40 - min(len(result_diff)*2, 40)
self.set_typo_score(temp)
result_diff.insert(0, temp)
return result_diff
# XML 파일 채점
def score_directory(self, xml_directory, answer_path):
# xml 파일 불러오기
xml_files = Path(xml_directory).glob('*.hml')
# 결과 저장할 리스트
results = []
for xml_file in xml_files:
result = {}
chart_xml = self.binary_to_chartxml(xml_file)
result['score'] = self._score_xml_file(xml_file, chart_xml)
result['typo'] = self.typo_check(answer_path, xml_file)
result['score'] = self._score_xml_file(xml_file, chart_xml)
# result['score']['score_results'][2]['points'] = result['typo'][0]
results.append(result)
return results
@@ -368,6 +375,7 @@ class XMLScorer:
number = match.group(1)
name = match.group(2)
return number, name
return None, None
def export_to_excel(self, results, output_path=None):
@@ -400,29 +408,46 @@ class XMLScorer:
else:
detail_row = {'채점항목':f"{number}-{name}"}
for i, scoring in enumerate(result['score_results']):
# detail_row[scoring['item']] = scoring['points']
detail_row[f'{i+1}'] = scoring['points']
section_num = None
partial_idx = 0
for i, score_result in enumerate(result['score_results']):
current_section = int(score_result['id'].split('-')[0])
if section_num is None:
section_num = current_section
if current_section != section_num:
# 이전 섹션의 부분합을 출력
detail_row[f'[{section_num}]합계'] = result['partial_scores'][partial_idx]['score']
partial_idx += 1
section_num = current_section
detail_row[f'{i+1}'] = score_result['points']
# 마지막 섹션의 부분합을 출력
if section_num is not None and partial_idx < len(result['partial_scores']):
detail_row[f'[{section_num}]합계'] = result['partial_scores'][partial_idx]['score']
detail_row['총점'] = result.get('total_score', 0)
detail_data.append(detail_row)
summary_df = pd.DataFrame(summary_data)
detail_df = pd.DataFrame(detail_data).transpose()
# detail_df = pd.DataFrame(detail_data)
for temp in results:
result = temp['typo']
typo_data.append(result)
type_df = pd.DataFrame(typo_data).transpose()
typo_df = pd.DataFrame(typo_data).transpose()
# detail_df = pd.DataFrame(detail_data)
detail_df.iloc[3] = typo_df.iloc[0]
# ExcelWriter 객체 생성
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
summary_df.to_excel(writer, sheet_name='채점결과요약', index=False)
detail_df.to_excel(writer, sheet_name='채점상세내역', index=False)
type_df.to_excel(writer, sheet_name='오타내역', index=False)
typo_df.to_excel(writer, sheet_name='오타내역', index=False)
# 열 너비 자동 조정
# for sheet_name in writer.sheets: