diff --git a/250526_DIW_2505회_A형_TEST.xlsx b/250526_DIW_2505회_A형_TEST.xlsx
deleted file mode 100644
index bb80e7a..0000000
Binary files a/250526_DIW_2505회_A형_TEST.xlsx and /dev/null differ
diff --git a/250526_DIW_2505회_B형_TEST.xlsx b/250526_DIW_2505회_B형_TEST.xlsx
deleted file mode 100644
index a393c31..0000000
Binary files a/250526_DIW_2505회_B형_TEST.xlsx and /dev/null differ
diff --git a/250526_DIW_2505회_C형_TEST.xlsx b/250526_DIW_2505회_C형_TEST.xlsx
deleted file mode 100644
index be780ff..0000000
Binary files a/250526_DIW_2505회_C형_TEST.xlsx and /dev/null differ
diff --git a/250526_DIW_2505회_D형_TEST.xlsx b/250526_DIW_2505회_D형_TEST.xlsx
deleted file mode 100644
index 31db4e6..0000000
Binary files a/250526_DIW_2505회_D형_TEST.xlsx and /dev/null differ
diff --git a/250604_DIW_2505C_TEST.xlsx b/250604_DIW_2505C_TEST.xlsx
new file mode 100644
index 0000000..3ab8645
Binary files /dev/null and b/250604_DIW_2505C_TEST.xlsx differ
diff --git a/250604_DIW_2505C_채점결과.xlsx b/250604_DIW_2505C_채점결과.xlsx
new file mode 100644
index 0000000..2842b65
Binary files /dev/null and b/250604_DIW_2505C_채점결과.xlsx differ
diff --git a/DIW_2505A.json b/DIW_2505A.json
index 3ac036c..44d9a8f 100644
--- a/DIW_2505A.json
+++ b/DIW_2505A.json
@@ -454,14 +454,14 @@
"item": "③ 크기-높이 (40 mm)"
},
"17": {
- "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION/@HorzOffset",
+ "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset",
"value": "0",
"points": 2,
"category": "mmSize",
"item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)"
},
"18": {
- "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION/@VertOffset",
+ "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset",
"value": "23",
"points": 2,
"category": "mmSize",
diff --git a/DIW_2505B.json b/DIW_2505B.json
index 5a7444c..316213b 100644
--- a/DIW_2505B.json
+++ b/DIW_2505B.json
@@ -456,14 +456,14 @@
"item": "③ 크기-높이 (40 mm)"
},
"17": {
- "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION/@HorzOffset",
+ "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset",
"value": "0",
"points": 2,
"category": "mmSize",
"item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)"
},
"18": {
- "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION/@VertOffset",
+ "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset",
"value": "24",
"points": 2,
"category": "mmSize",
diff --git a/DIW_2505C.json b/DIW_2505C.json
index fd15754..f9ab7ef 100644
--- a/DIW_2505C.json
+++ b/DIW_2505C.json
@@ -456,14 +456,14 @@
"item": "③ 크기-높이 (40 mm)"
},
"17": {
- "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION/@HorzOffset",
+ "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@HorzOffset",
"value": "0",
"points": 2,
"category": "mmSize",
"item": "④ 위치 (어울림 : 가로-쪽의 왼쪽 0.0mm)"
},
"18": {
- "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION/@VertOffset",
+ "path": "//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true') and @HorzRelTo='Page']/@VertOffset",
"value": "24",
"points": 2,
"category": "mmSize",
diff --git a/diwScoring2.py b/diwScoring2.py
index 85e32de..787585c 100644
--- a/diwScoring2.py
+++ b/diwScoring2.py
@@ -126,6 +126,19 @@ class XMLScorer:
# 하나의 XML 파일 채점
def _score_xml_file(self, xml_file, chart_xml):
+
+ def extract_char_text_from_p(p_element):
+ """
+ 주어진
요소에서 모든 자손 의 텍스트를 추출해 문자열 리스트로 반환합니다.
+ """
+ full_text = []
+ for p in p_element:
+ char_elements = p.xpath('.//CHAR')
+ combined_text = ''.join([char.text for char in char_elements if char.text])
+ no_space_text = re.sub(r'\s+', '', combined_text) # 공백 문자 제거
+ full_text.append(no_space_text)
+ return full_text
+
try:
tree = ET.parse(xml_file)
root = tree.getroot()
@@ -373,6 +386,7 @@ class XMLScorer:
elif (category or "") == "mmSize":
items = root.xpath(xpath)
+
# 오차범위 설정
# 한글 프로그램 내부에서 드물게 0mm이지만 1pt로 저장되는 경우가 있음
#
@@ -385,13 +399,16 @@ class XMLScorer:
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)
+ if not items:
+ scoring['points'] = 0
+ else:
+ for item in items:
+ user_answer = float(item)
- self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range)
-
- if scoring['points'] > 0:
- break
+ self.evaluate_answer(scoring, user_answer, right_answer, points, method="tolerance", tolerance=error_range)
+
+ if scoring['points'] > 0:
+ break
elif (category or "") == "ParaShape":
items = root.xpath(xpath)
@@ -505,11 +522,27 @@ class XMLScorer:
# 폰트 속성
elif (category or "") == "FontAttribute":
# 하이퍼링크 처리
- hyperlink_ptag = criterion.get('hyperlink_ptag', None)
- has_hyperlink_ptag = root.xpath(hyperlink_ptag) if hyperlink_ptag else False
+
+ # 1. 하이퍼링크를 포함하는 P요소를 가져옴
+ # 2. 그 P요소의 자손 CHAR태그에 있는 텍스트를 하나의 문자열로 변환
+ # 3. P요소의 문자열과 채점하려는 문자열이 일치하는지 확인
+ hyperlink_xpath = criterion.get('hyperlink_ptag', None)
+ hyperlink_ptag = root.xpath(hyperlink_xpath) if hyperlink_xpath else None
+
+ p_tag_text_list = extract_char_text_from_p(hyperlink_ptag) if hyperlink_ptag else []
+ hyperlink_text = search_value.replace(" ", "") if search_value else ""
+
+ # search_value가 hyperlink문자열에 포함되어 있는지 확인
+ # search_value가 hyperlink인 경우와 아닌경우를 구분해 채점
+ search_in_hyperlink = False
+ if hyperlink_text and any(hyperlink_text in text for text in p_tag_text_list):
+ search_in_hyperlink = True
+ else:
+ search_in_hyperlink = False
# hyperlink가 아닌 경우(일반적인 텍스트 일 경우)
- if not has_hyperlink_ptag:
+ # 하이퍼링크를 포함한 P태그가 없거나 search_value값이 하이퍼링크텍스트에 포함되어 있지 않을 경우
+ if not hyperlink_ptag or not search_in_hyperlink:
charshape_list = root.xpath(xpath)
if not charshape_list:
charshape = None
@@ -528,10 +561,9 @@ class XMLScorer:
break
# 하이퍼링크인 경우
- elif has_hyperlink_ptag:
- hyperlink_text = search_value.replace(" ", "")
-
- p_elements = has_hyperlink_ptag
+ # elif hyperlink_ptag and search_in_hyperlink:
+ else:
+ p_elements = hyperlink_ptag
for p in p_elements:
# 수험자가 입력한 텍스트 중 하이퍼링크가 들어간 문단의 모든 텍스트를 가져와
@@ -1050,13 +1082,13 @@ def main():
# 채점하고자 하는 유형은 주석 해제
exam_types = [
# 'A',
- 'B',
- # 'C',
+ # 'B',
+ 'C',
# 'D',
]
- test_mode = False
- # test_mode = True #/TEST 폴더 채점시
+ # test_mode = False
+ test_mode = True #/TEST 폴더 채점시
output_excel_paths = []
for exam_type in exam_types:
diff --git a/zzz.xbook b/zzz.xbook
index 165fd1c..fba88b1 100644
--- a/zzz.xbook
+++ b/zzz.xbook
@@ -1 +1 @@
-[{"kind":2,"language":"xpath","value":"//a:t[text()='클라우드 보안투자']/ancestor::a:r//a:ea/@typeface"},{"kind":2,"language":"xpath","value":"boolean(//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕' and //CHARSHAPE/@Height='1000' and //PARASHAPE/PARAMARGIN/@LineSpacing='160' and //PARASHAPE/@Align='Justify')"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕'"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕' and //CHARSHAPE/@Height='1000' and //PARASHAPE/PARAMARGIN/@LineSpacing='160' and //PARASHAPE/@Align='Justify')"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT/@Name"},{"kind":2,"language":"xpath","value":"//CHARSHAPE/@Height"},{"kind":2,"language":"xpath","value":"//c:valAx//a:defRPr/@sz"},{"kind":2,"language":"xpath","value":"//c:catAx/c:txPr//a:defRPr/@i"},{"kind":2,"language":"xpath","value":"//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Width"}]
\ No newline at end of file
+[{"kind":2,"language":"xpath","value":"//a:t[text()='클라우드 보안투자']/ancestor::a:r//a:ea/@typeface"},{"kind":2,"language":"xpath","value":"boolean(//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕' and //CHARSHAPE/@Height='1000' and //PARASHAPE/PARAMARGIN/@LineSpacing='160' and //PARASHAPE/@Align='Justify')"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕'"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT[@Id=//CHARSHAPE/FONTID/@Hangul]/@Name='바탕' and //CHARSHAPE/@Height='1000' and //PARASHAPE/PARAMARGIN/@LineSpacing='160' and //PARASHAPE/@Align='Justify')"},{"kind":2,"language":"xpath","value":"//FONTFACE[@Lang='Hangul']/FONT/@Name"},{"kind":2,"language":"xpath","value":"//CHARSHAPE/@Height"},{"kind":2,"language":"xpath","value":"//P[.//FIELDBEGIN[@Type='Hyperlink'] and .//CHAR[contains(., 'http')]]"},{"kind":2,"language":"xpath","value":"//P[.//FIELDBEGIN[@Type='Hyperlink'] and .//CHAR[contains(., 'http')]]"},{"kind":2,"language":"xpath","value":"//PICTURE[./IMAGE[@BinItem=//BINITEM[@Format='JPG']/@BinData]]/SHAPEOBJECT/POSITION[not(@TreatAsChar='true')]/@HorzOffset"},{"kind":2,"language":"xpath","value":"//BORDERFILL[@Id=//TABLE/ROW[1]/CELL/@BorderFill]/BOTTOMBORDER/@Width"}]
\ No newline at end of file
diff --git a/250527_DIW_2505회_A형_채점결과.xlsx b/회차별채점자료/2505/excel_채점결과/250527_DIW_2505회_A형_채점결과.xlsx
similarity index 100%
rename from 250527_DIW_2505회_A형_채점결과.xlsx
rename to 회차별채점자료/2505/excel_채점결과/250527_DIW_2505회_A형_채점결과.xlsx
diff --git a/250527_DIW_2505회_B형_채점결과.xlsx b/회차별채점자료/2505/excel_채점결과/250527_DIW_2505회_B형_채점결과.xlsx
similarity index 100%
rename from 250527_DIW_2505회_B형_채점결과.xlsx
rename to 회차별채점자료/2505/excel_채점결과/250527_DIW_2505회_B형_채점결과.xlsx
diff --git a/250527_DIW_2505회_C형_채점결과.xlsx b/회차별채점자료/2505/excel_채점결과/250527_DIW_2505회_C형_채점결과.xlsx
similarity index 100%
rename from 250527_DIW_2505회_C형_채점결과.xlsx
rename to 회차별채점자료/2505/excel_채점결과/250527_DIW_2505회_C형_채점결과.xlsx
diff --git a/250529_DIW_2505회_B형_채점결과.xlsx b/회차별채점자료/2505/excel_채점결과/250529_DIW_2505회_B형_채점결과.xlsx
similarity index 100%
rename from 250529_DIW_2505회_B형_채점결과.xlsx
rename to 회차별채점자료/2505/excel_채점결과/250529_DIW_2505회_B형_채점결과.xlsx
diff --git a/250529_DIW_2505회_C형_채점결과.xlsx b/회차별채점자료/2505/excel_채점결과/250529_DIW_2505회_C형_채점결과.xlsx
similarity index 100%
rename from 250529_DIW_2505회_C형_채점결과.xlsx
rename to 회차별채점자료/2505/excel_채점결과/250529_DIW_2505회_C형_채점결과.xlsx
diff --git a/250529_DIW_2505회_D형_채점결과.xlsx b/회차별채점자료/2505/excel_채점결과/250529_DIW_2505회_D형_채점결과.xlsx
similarity index 100%
rename from 250529_DIW_2505회_D형_채점결과.xlsx
rename to 회차별채점자료/2505/excel_채점결과/250529_DIW_2505회_D형_채점결과.xlsx