diff --git a/02_conversion_hwp_to_xml.py b/02_conversion_hwp_to_xml.py index 0400137..2acd659 100644 --- a/02_conversion_hwp_to_xml.py +++ b/02_conversion_hwp_to_xml.py @@ -147,11 +147,11 @@ if __name__ == "__main__": # 배열 동시에 변환하면 에러발생 -> 하나씩 변환 -> time.sleep(0.5) 추가 for exam_round in exam_rounds: folders = [ - (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\A\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\A\\DIW"), - (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\B\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\B\\DIW"), - (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\C\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\C\\DIW"), - (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\D\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\D\\DIW"), - # (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\E\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\E\\DIW"), + # (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\A\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\A\\DIW"), + # (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\B\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\B\\DIW"), + # (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\C\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\C\\DIW"), + # (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\D\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\D\\DIW"), + (f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\input\\{exam_round}\\E\\DIW",f"C:\\Users\\dra\\project\\HWP\\HWP-Scoring\\output\\{exam_round}\\E\\DIW"), ] # 변환 실행 diff --git a/250605_DIW_2505B_TEST.xlsx b/250605_DIW_2505B_TEST.xlsx new file mode 100644 index 0000000..0ae92be Binary files /dev/null and b/250605_DIW_2505B_TEST.xlsx differ diff --git a/250605_DIW_2505C_TEST.xlsx b/250605_DIW_2505C_TEST.xlsx new file mode 100644 index 0000000..f11b1c2 Binary files /dev/null and b/250605_DIW_2505C_TEST.xlsx differ diff --git a/DIW_2505A.json b/DIW_2505A.json index 44d9a8f..3a2a951 100644 --- a/DIW_2505A.json +++ b/DIW_2505A.json @@ -255,7 +255,7 @@ "item": "문구 (운봉바래봉철쭉제)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "궁서", "points": 1, @@ -311,12 +311,11 @@ } }, "30": { - "path": "not(//PARASHAPE[@Id=//SECTION[1]/P/@ParaShape]/PARAMARGIN[@LineSpacing!='{option}'])", - "option": "200", - "value": true, + "path": "//PARASHAPE[@Id='{parashape_id}']/PARAMARGIN/@LineSpacing", + "value": "200", "points": 2, - "category": "Boolean", - "item": "문제 1 줄간격 200% 설정", + "category": "LineSpacing", + "item": "문제 1 줄간격 180% 설정", "desc": "1페이지 문단의 줄간격이 정답이 아닌 문단이 있으면 False(감점)" } }, @@ -341,7 +340,7 @@ "desc": "섹션이 1개 이상이면 점수부여" }, "3": { - "path": "//COLDEF/@Count", + "path": "//P[@PageBreak='true']//COLDEF/@Count", "value": "2", "points": 3, "category": "OneAnswer", diff --git a/DIW_2505B.json b/DIW_2505B.json index 316213b..ba110c8 100644 --- a/DIW_2505B.json +++ b/DIW_2505B.json @@ -255,7 +255,7 @@ "item": "문구 (광양매실축제위원회)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "굴림", "points": 1, @@ -313,11 +313,10 @@ } }, "30": { - "path": "not(//PARASHAPE[@Id=//SECTION[1]/P/@ParaShape]/PARAMARGIN[@LineSpacing!='{option}'])", - "option": "180", - "value": true, + "path": "//PARASHAPE[@Id='{parashape_id}']/PARAMARGIN/@LineSpacing", + "value": "180", "points": 2, - "category": "Boolean", + "category": "LineSpacing", "item": "문제 1 줄간격 180% 설정", "desc": "1페이지 문단의 줄간격이 정답이 아닌 문단이 있으면 False(감점)" } diff --git a/DIW_2505C.json b/DIW_2505C.json index f9ab7ef..e42e631 100644 --- a/DIW_2505C.json +++ b/DIW_2505C.json @@ -255,7 +255,7 @@ "item": "문구 (별사랑천문대)/③ 정렬 (가운데 정렬)" }, "25": { - "path": "//TEXT[CHAR[text()='{searchValue}']]/@CharShape", + "path": "//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@CharShape", "searchValue": "DIAT", "value": "돋움", "points": 1, @@ -313,11 +313,10 @@ } }, "30": { - "path": "not(//PARASHAPE[@Id=//SECTION[1]/P/@ParaShape]/PARAMARGIN[@LineSpacing!='{option}'])", - "option": "180", - "value": true, + "path": "//PARASHAPE[@Id='{parashape_id}']/PARAMARGIN/@LineSpacing", + "value": "180", "points": 2, - "category": "Boolean", + "category": "LineSpacing", "item": "문제 1 줄간격 180% 설정", "desc": "1페이지 문단의 줄간격이 정답이 아닌 문단이 있으면 False(감점)" } diff --git a/diwScoring2.py b/diwScoring2.py index 787585c..c440ad2 100644 --- a/diwScoring2.py +++ b/diwScoring2.py @@ -605,14 +605,38 @@ class XMLScorer: for elem in p.iter(): # 시작 지점 확인 + # FIELDBEGIN태그와 FIELDEND태그 사이 if elem.tag == "FIELDBEGIN": inside_field = True elif elem.tag == "FIELDEND": inside_field = False + + # 하이퍼링크 텍스트가 CharShape 속성값이 앞의 텍스트와 다른 경우 + # http://www.ihd.or.kr 주소가 TEXT 부모태그를 가지는 경우 + # [예시] + # + # http://www.ihd.or.kr) + # + # 해당 부모 TEXT태그의 CharShape속성을 확인 elif inside_field and elem.tag == "TEXT": charshape = elem.get("CharShape") + print('charshape : ', charshape) if charshape: charshape_list.append(charshape) + + # 하이퍼링크 텍스트가 CharShape 속성값이 앞의 텍스트와 같은 경우 + # http://www.ihd.or.kr 주소가 TEXT부모태그 없이 CHAR로만 있는경우 + # [예시] + # http://www.ihd.or.kr) + # FIELDBEGIN밖의 TEXT태그의 CharShape속성을 확인해야 한다 + elif inside_field and elem.tag == "CHAR": + parent = elem.getparent() + + charshape = parent.get("CharShape") + print('charshape : ', charshape) + if charshape: + charshape_list.append(charshape) + # 하이퍼링크에 해당하는 P태그 내 존재하는 charshape ID값 모두를 비교해 해당 속성(ITALIC, BOLD, UNDERLINE) 확인 # 모든 charshape ID값이 정답과 일치하는 경우에만 점수 부여 @@ -636,7 +660,37 @@ class XMLScorer: else: self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") + elif (category or "") == "LineSpacing": + # //SECTION[1](1페이지의) 모든 P요소 + all_p_tags = root.xpath("//SECTION[1]/P") + # 구역이 나뉘어 있지 않은 답안의 처리 + # 수험자가 구역 나눔을 적용하지 않고 2페이지 답안을 처리하기 위해서 + # [Control+Enter]를 이용해 쪽 나눔을 적용하는 부분을 검색 + # P태그의 PageBreak속성값이 'true'가 나오기 전까지의 P태그만 확인 + p_tags_before_pagebreak = [] + for p in all_p_tags: + if p.get('PageBreak') == 'true': + break + else: + p_tags_before_pagebreak.append(p) + + # 줄간격이 하나라도 일치하지 않을 경우 오답처리 + linespacing_match = True + for p in p_tags_before_pagebreak: + parashape_id = p.get('ParaShape') + xpath = xpath.replace('{parashape_id}', parashape_id) + linespacing = root.xpath(xpath) + user_answer = linespacing[0] + + if user_answer != right_answer: + linespacing_match = False + break + + if linespacing_match is True: + self.evaluate_answer(scoring, user_answer, right_answer, points, method="equal") + else: + self.evaluate_answer(scoring, user_answer, right_answer, 0, method="equal") # 특수문자 갯수 채점 @@ -1082,8 +1136,8 @@ def main(): # 채점하고자 하는 유형은 주석 해제 exam_types = [ # 'A', - # 'B', - 'C', + 'B', + # 'C', # 'D', ] diff --git a/hwp_conversion.log b/hwp_conversion.log index cd780ba..f041226 100644 --- a/hwp_conversion.log +++ b/hwp_conversion.log @@ -15578,3 +15578,46 @@ 2025-05-29 14:56:51,294 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\D\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\D\DIW 2025-05-29 14:56:54,879 - INFO - 변환 성공: DIW_2505D.hwpx -> DIW_2505D.hml 2025-05-29 14:56:55,341 - INFO - 폴더 변환 완료: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\D\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\D\DIW +2025-06-05 17:25:47,349 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:25:50,519 - INFO - 변환 성공: 워드(한글)_002386_박세진.hwp -> 워드(한글)_002386_박세진.hml +2025-06-05 17:25:50,556 - INFO - 변환 성공: 워드(한글)_002387_하인애.hwp -> 워드(한글)_002387_하인애.hml +2025-06-05 17:25:50,577 - INFO - 폴더 변환 완료: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:40:46,611 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:41:16,399 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:42:03,851 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:42:10,189 - INFO - 변환 성공: 워드(한글)_002386_박세진.hwp -> 워드(한글)_002386_박세진.hml +2025-06-05 17:42:12,282 - INFO - 변환 성공: 워드(한글)_002387_하인애.hwp -> 워드(한글)_002387_하인애.hml +2025-06-05 17:42:12,304 - INFO - 폴더 변환 완료: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:43:21,499 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:48:40,064 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:48:43,358 - INFO - 변환 성공: 워드(한글)-000437-김재명.hwp -> 워드(한글)-000437-김재명.hml +2025-06-05 17:48:44,675 - INFO - 변환 성공: 워드(한글)-004040-이경표.hwp -> 워드(한글)-004040-이경표.hml +2025-06-05 17:48:45,477 - INFO - 변환 성공: 워드(한글)-009585-윤도현.hwp -> 워드(한글)-009585-윤도현.hml +2025-06-05 17:48:46,495 - INFO - 변환 성공: 워드(한글)-009587-김현준.hwp -> 워드(한글)-009587-김현준.hml +2025-06-05 17:48:47,369 - INFO - 변환 성공: 워드(한글)-009589-김효진.hwp -> 워드(한글)-009589-김효진.hml +2025-06-05 17:48:48,291 - INFO - 변환 성공: 워드(한글)-009590-김윤주.hwp -> 워드(한글)-009590-김윤주.hml +2025-06-05 17:48:49,077 - INFO - 변환 성공: 워드(한글)-009593-송민서.hwp -> 워드(한글)-009593-송민서.hml +2025-06-05 17:48:49,925 - INFO - 변환 성공: 워드(한글)-009596-이현서.hwp -> 워드(한글)-009596-이현서.hml +2025-06-05 17:48:51,033 - INFO - 변환 성공: 워드(한글)-009603-신재진.hwp -> 워드(한글)-009603-신재진.hml +2025-06-05 17:48:51,238 - INFO - 변환 성공: 워드(한글)_002386_박세진.hwp -> 워드(한글)_002386_박세진.hml +2025-06-05 17:48:51,263 - INFO - 변환 성공: 워드(한글)_002387_하인애.hwp -> 워드(한글)_002387_하인애.hml +2025-06-05 17:48:51,285 - INFO - 폴더 변환 완료: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:49:47,398 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:49:50,824 - INFO - 변환 성공: 워드(한글)_002386_박세진.hwp -> 워드(한글)_002386_박세진.hml +2025-06-05 17:49:51,067 - INFO - 변환 성공: 워드(한글)_002386_박세진2.hwp -> 워드(한글)_002386_박세진2.hml +2025-06-05 17:49:51,377 - INFO - 변환 성공: 워드(한글)_002387_하인애.hwp -> 워드(한글)_002387_하인애.hml +2025-06-05 17:49:51,613 - INFO - 변환 성공: 워드(한글)_002386_박세진3.hwpx -> 워드(한글)_002386_박세진3.hml +2025-06-05 17:49:52,046 - INFO - 폴더 변환 완료: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:53:04,312 - INFO - 폴더 변환 시작: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW +2025-06-05 17:53:08,688 - INFO - 변환 성공: 워드(한글)_002386_박세진.hwp -> 워드(한글)_002386_박세진.hml +2025-06-05 17:53:08,720 - INFO - 변환 성공: 워드(한글)_002387_하인애.hwp -> 워드(한글)_002387_하인애.hml +2025-06-05 17:53:08,981 - INFO - 변환 성공: 워드(한글)_001285_홍민기.hwpx -> 워드(한글)_001285_홍민기.hml +2025-06-05 17:53:09,653 - INFO - 변환 성공: 워드(한글)_001634_김지유.hwpx -> 워드(한글)_001634_김지유.hml +2025-06-05 17:53:10,287 - INFO - 변환 성공: 워드(한글)_001819_정의준.hwpx -> 워드(한글)_001819_정의준.hml +2025-06-05 17:53:10,903 - INFO - 변환 성공: 워드(한글)_001820_이서현.hwpx -> 워드(한글)_001820_이서현.hml +2025-06-05 17:53:11,562 - INFO - 변환 성공: 워드(한글)_002388_강윤.hwpx -> 워드(한글)_002388_강윤.hml +2025-06-05 17:53:12,276 - INFO - 변환 성공: 워드(한글)_002389_정유찬.hwpx -> 워드(한글)_002389_정유찬.hml +2025-06-05 17:53:12,895 - INFO - 변환 성공: 워드(한글)_002390_정현희.hwpx -> 워드(한글)_002390_정현희.hml +2025-06-05 17:53:13,413 - INFO - 변환 성공: 워드(한글)_002391_김지우.hwpx -> 워드(한글)_002391_김지우.hml +2025-06-05 17:53:14,078 - INFO - 변환 성공: 워드(한글)_00349_이재용.hwpx -> 워드(한글)_00349_이재용.hml +2025-06-05 17:53:14,474 - INFO - 폴더 변환 완료: C:\Users\dra\project\HWP\HWP-Scoring\input\2505\E\DIW -> C:\Users\dra\project\HWP\HWP-Scoring\output\2505\E\DIW diff --git a/zzz.xbook b/zzz.xbook index fba88b1..4c0d068 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":"//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 +[{"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":"//SECTION[1]//TEXT[CHAR[text()='DIAT']]/@CharShape"},{"kind":2,"language":"xpath","value":"//CHARSHAPE[@Id=//SECTION[1]//TEXT[CHAR[text()='{searchValue}']]/@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/회차별채점자료/2505/2505확인필요.xlsx b/회차별채점자료/2505/2505확인필요.xlsx new file mode 100644 index 0000000..a42c6ca Binary files /dev/null and b/회차별채점자료/2505/2505확인필요.xlsx differ diff --git a/회차별채점자료/2505/excel_채점기준표/DIW_2505C.xlsx b/회차별채점자료/2505/excel_채점기준표/DIW_2505C.xlsx index f8f6bee..a2ebf49 100644 Binary files a/회차별채점자료/2505/excel_채점기준표/DIW_2505C.xlsx and b/회차별채점자료/2505/excel_채점기준표/DIW_2505C.xlsx differ