diff --git a/01_copy_files.py b/01_copy_files.py index cbc68a0..869962f 100644 --- a/01_copy_files.py +++ b/01_copy_files.py @@ -76,7 +76,7 @@ if __name__ == "__main__": exam_round = "2622" exam_codes = ["DIC", "DPI"] # exam_codes = ["DIC"] - source_dir = r"D:\project\GOM\DIC\회차별채점자료\2622" - # source_dir = r"D:\project\data\제2522회 특별\(추가)과목별_답안파일" + # source_dir = r"D:\project\GOM\DIC\회차별채점자료\2622" + source_dir = r"D:\project\data\제2622회 특별\과목별답안파일 (2)" copy_exam_files(exam_round, exam_codes, source_dir) diff --git a/findSimilarString.js b/findSimilarString.js index ddbe3b9..12dbb45 100644 --- a/findSimilarString.js +++ b/findSimilarString.js @@ -9,7 +9,7 @@ const stringSimilarity = require("string-similarity"); * @param {number} threshold - 유사도 기준 (0~1) * @returns {string} - 유사한 문자열 */ -function findSimilarString(xmlDoc, targetString, threshold = 0.8) { +function findSimilarString(xmlDoc, targetString, threshold = 0.7) { // XML 내부의 비교 대상 텍스트 리스트 찾기 function getTextNodes(xmlDoc, paths = ["//CRCUnitArr/@Name"]) { const stringList = []; diff --git a/gpdpScoring.js b/gpdpScoring.js index eddbaf1..6c7de8a 100644 --- a/gpdpScoring.js +++ b/gpdpScoring.js @@ -172,7 +172,7 @@ function getGpdpScore(gpdpData, scoringJson, index) { * > 멀티라인 텍스트 유사도 판별하기 어려움 */ if (search !== undefined) { - let result = findSimilarString(gpdpXmlDoc, search, 0.8); + let result = findSimilarString(gpdpXmlDoc, search, 0.7); if (result !== null) { result = result.replace(/"/g, "'"); search = result; @@ -202,6 +202,11 @@ function getGpdpScore(gpdpData, scoringJson, index) { // [1-4] 사진1 > 조정 else if (type === "layer.Effects") { + if (!ele) { + scoringResult[key] = '확인필요'; + console.log("❌ 오답: 레이어명 확인 필요"); + continue; + } const effects = ele ? xpath.select(ele, gpdpXmlDoc) : []; let isMatched = false; diff --git a/psdExport_2.js b/psdExport_2.js index 55e3350..5597bc2 100644 --- a/psdExport_2.js +++ b/psdExport_2.js @@ -14,20 +14,20 @@ const todayDate = getToday(); const examRound = '2622'; const codeTypes = [ - 'DIC', + // 'DIC', 'DPI', ]; const examTypes = [ 'A', - 'B', - 'C', + // 'B', + // 'C', // 'D' ]; // testMode가 true일 경우 TEST 폴더에 있는 답안 파일을 읽어옴 -const testMode = false; -// const testMode = true; +// const testMode = false; +const testMode = true; const outputExcelFiles = []; codeTypes.forEach(codeType => { @@ -36,9 +36,15 @@ codeTypes.forEach(codeType => { if (!fs.existsSync(jsonPath)) return const scoringJson = require(jsonPath); const answerFilesDir = `./output/${examRound}/${type}/${testMode ? 'TEST' : codeType}`; - let outputExcelFile = `./score_result/${todayDate}_${codeType}_${examRound}${type}_채점결과.xlsx`; + let outputExcelFile = + `./score_result/${examRound}/${todayDate}_${codeType}_${examRound}${type}_채점결과.xlsx`; + // 폴더 경로 추출 + const dirPath = path.dirname(outputExcelFile); + // 폴더가 없으면 생성 + fs.mkdirSync(dirPath, { recursive: true }); + if (testMode) { - outputExcelFile = `./00_${codeType}_${examRound}${type}_TEST.xlsx`; + outputExcelFile = `./score_result/test/00_${codeType}_${examRound}${type}_TEST.xlsx`; } // 답안 폴더 내부에 디렉토리가 아닌 일반 파일이 있을 경우 디렉토리만 필터링 해서 불러옴 @@ -91,17 +97,59 @@ codeTypes.forEach(codeType => { console.error(`Error reading PSD file: ${psdPath}`, error); } }); + // 기존 XML 파일 채점 방식 주석 처리 (20260213) gpdpFiles.forEach((gpdpFile, index) => { const gpdpPath = path.join('./', studentDir, gpdpFile); console.log(`Reading ${gpdpPath}...`); const xmlString = fs.readFileSync(gpdpPath, 'utf8'); - // XML 문자열을 파싱하여 XML 문서 객체로 변환 const xmlDocument = new DOMParser().parseFromString(xmlString, 'application/xml'); - // console.log('xmlDocument:', xmlDocument); - scoringResult[index + 1] = getGpdpScore(xmlDocument, scoringJson, index + 4); + if (!xmlString.trim().startsWith("<")) { + console.warn(`XML 형태 아님 → 스킵: ${gpdpFile}`); + return; + } + + // 260219 - 파일명에서 번호 추출하여 점수 계산에 활용 + // 파일명에서 번호 추출 (dpi_01_, dpi_02_ ) + const fileNumberMatch = gpdpFile.match(/dpi_(\d+)_/); + const fileNumber = fileNumberMatch ? parseInt(fileNumberMatch[1], 10) : index + 1; + + // 추출한 번호를 사용하여 scoringResult에 저장 + scoringResult[fileNumber] = getGpdpScore(xmlDocument, scoringJson, fileNumber + 3); }); + // gpdpFiles.forEach((gpdpFile, index) => { + // const gpdpPath = path.join("./", studentDir, gpdpFile); + // console.log(`Reading ${gpdpPath}...`); + + // let xmlString; + // try { + // xmlString = fs.readFileSync(gpdpPath, "utf8"); + // } catch (err) { + // console.warn(`파일 읽기 실패, 스킵: ${gpdpPath}`); + // return; + // } + + // const xmlDocument = new DOMParser().parseFromString( + // xmlString, + // "application/xml" + // ); + + // // ✅ XML 파싱 실패 여부 확인 + // const parseError = xmlDocument.getElementsByTagName("parsererror"); + + // if (parseError.length > 0) { + // console.warn(`XML 아님 → 스킵: ${gpdpFile}`); + // return; // 그냥 패스 + // } + + // // 정상 XML만 점수 계산 + // scoringResult[index + 1] = getGpdpScore( + // xmlDocument, + // scoringJson, + // index + 4 + // ); + // }); if (gmepFile.length === 0) { // 곰믹스 채점 항목 갯수 const gmepItemCount = Object.keys(scoringJson[2]).length; @@ -139,6 +187,10 @@ codeTypes.forEach(codeType => { const workbook = XLSX.utils.book_new(); // 열 너비 계산 + if (!Array.isArray(transposedData) || transposedData.length === 0) { + console.warn("transposedData 비어 있음 → 엑셀 컬럼 생성 스킵"); + return; // 또는 continue / break (문맥에 따라) + } const columnWidths = Object.keys(transposedData[0]).map(key => { // 각 열의 최대 길이를 계산 const maxLength = Math.max( diff --git a/score_result/260211_DPI_2622B_채점결과.xlsx b/score_result/260211_DPI_2622B_채점결과.xlsx deleted file mode 100644 index aaa88b3..0000000 Binary files a/score_result/260211_DPI_2622B_채점결과.xlsx and /dev/null differ diff --git a/score_result/260212_DIC_2622B_채점결과.xlsx b/score_result/260212_DIC_2622B_채점결과.xlsx deleted file mode 100644 index 7d4347b..0000000 Binary files a/score_result/260212_DIC_2622B_채점결과.xlsx and /dev/null differ diff --git a/score_result/260212_DPI_2622A_채점결과.xlsx b/score_result/260212_DPI_2622A_채점결과.xlsx deleted file mode 100644 index 1995f39..0000000 Binary files a/score_result/260212_DPI_2622A_채점결과.xlsx and /dev/null differ diff --git a/score_result/260212_DPI_2622B_채점결과.xlsx b/score_result/260212_DPI_2622B_채점결과.xlsx deleted file mode 100644 index 56bd26b..0000000 Binary files a/score_result/260212_DPI_2622B_채점결과.xlsx and /dev/null differ diff --git a/score_result/260212_DPI_2622C_채점결과.xlsx b/score_result/260212_DPI_2622C_채점결과.xlsx deleted file mode 100644 index f55299b..0000000 Binary files a/score_result/260212_DPI_2622C_채점결과.xlsx and /dev/null differ diff --git a/score_result/2622/260213_DIC_2622B_채점결과.xlsx b/score_result/2622/260213_DIC_2622B_채점결과.xlsx new file mode 100644 index 0000000..bd6f586 Binary files /dev/null and b/score_result/2622/260213_DIC_2622B_채점결과.xlsx differ diff --git a/score_result/2622/260213_DPI_2622A_채점결과.xlsx b/score_result/2622/260213_DPI_2622A_채점결과.xlsx new file mode 100644 index 0000000..d02b36c Binary files /dev/null and b/score_result/2622/260213_DPI_2622A_채점결과.xlsx differ diff --git a/score_result/2622/260213_DPI_2622B_채점결과.xlsx b/score_result/2622/260213_DPI_2622B_채점결과.xlsx new file mode 100644 index 0000000..26eded4 Binary files /dev/null and b/score_result/2622/260213_DPI_2622B_채점결과.xlsx differ diff --git a/score_result/2622/260213_DPI_2622C_채점결과.xlsx b/score_result/2622/260213_DPI_2622C_채점결과.xlsx new file mode 100644 index 0000000..c6281de Binary files /dev/null and b/score_result/2622/260213_DPI_2622C_채점결과.xlsx differ diff --git a/score_result/2622/260219_DPI_2622A_채점결과.xlsx b/score_result/2622/260219_DPI_2622A_채점결과.xlsx new file mode 100644 index 0000000..3ded948 Binary files /dev/null and b/score_result/2622/260219_DPI_2622A_채점결과.xlsx differ diff --git a/score_result/2622/260219_DPI_2622B_채점결과.xlsx b/score_result/2622/260219_DPI_2622B_채점결과.xlsx new file mode 100644 index 0000000..9c7ecc3 Binary files /dev/null and b/score_result/2622/260219_DPI_2622B_채점결과.xlsx differ diff --git a/score_result/2622/260219_DPI_2622C_채점결과.xlsx b/score_result/2622/260219_DPI_2622C_채점결과.xlsx new file mode 100644 index 0000000..80d4649 Binary files /dev/null and b/score_result/2622/260219_DPI_2622C_채점결과.xlsx differ diff --git a/score_result/260212_DIC_2622C_채점결과.xlsx b/score_result/test/00_DIC_2622B_TEST.xlsx similarity index 62% rename from score_result/260212_DIC_2622C_채점결과.xlsx rename to score_result/test/00_DIC_2622B_TEST.xlsx index 29bc1c1..51ae315 100644 Binary files a/score_result/260212_DIC_2622C_채점결과.xlsx and b/score_result/test/00_DIC_2622B_TEST.xlsx differ diff --git a/score_result/260211_DIC_2622B_채점결과.xlsx b/score_result/test/00_DPI_2622A_TEST.xlsx similarity index 65% rename from score_result/260211_DIC_2622B_채점결과.xlsx rename to score_result/test/00_DPI_2622A_TEST.xlsx index 7d4347b..09af768 100644 Binary files a/score_result/260211_DIC_2622B_채점결과.xlsx and b/score_result/test/00_DPI_2622A_TEST.xlsx differ diff --git a/score_result/260211_DPI_2622A_채점결과.xlsx b/score_result/test/00_DPI_2622B_TEST.xlsx similarity index 59% rename from score_result/260211_DPI_2622A_채점결과.xlsx rename to score_result/test/00_DPI_2622B_TEST.xlsx index 1995f39..abca016 100644 Binary files a/score_result/260211_DPI_2622A_채점결과.xlsx and b/score_result/test/00_DPI_2622B_TEST.xlsx differ diff --git a/score_result/260126_DIC_2601B_채점결과.xlsx b/회차별채점자료/2601/260126_DIC_2601B_채점결과.xlsx similarity index 100% rename from score_result/260126_DIC_2601B_채점결과.xlsx rename to 회차별채점자료/2601/260126_DIC_2601B_채점결과.xlsx diff --git a/score_result/260126_DIC_2601C_채점결과.xlsx b/회차별채점자료/2601/260126_DIC_2601C_채점결과.xlsx similarity index 100% rename from score_result/260126_DIC_2601C_채점결과.xlsx rename to 회차별채점자료/2601/260126_DIC_2601C_채점결과.xlsx diff --git a/score_result/260126_DPI_2601A_채점결과.xlsx b/회차별채점자료/2601/260126_DPI_2601A_채점결과.xlsx similarity index 100% rename from score_result/260126_DPI_2601A_채점결과.xlsx rename to 회차별채점자료/2601/260126_DPI_2601A_채점결과.xlsx diff --git a/score_result/260126_DPI_2601B_채점결과.xlsx b/회차별채점자료/2601/260126_DPI_2601B_채점결과.xlsx similarity index 100% rename from score_result/260126_DPI_2601B_채점결과.xlsx rename to 회차별채점자료/2601/260126_DPI_2601B_채점결과.xlsx diff --git a/score_result/260128_DIC_2601B_채점결과.xlsx b/회차별채점자료/2601/260128_DIC_2601B_채점결과.xlsx similarity index 100% rename from score_result/260128_DIC_2601B_채점결과.xlsx rename to 회차별채점자료/2601/260128_DIC_2601B_채점결과.xlsx diff --git a/score_result/260128_DIC_2601C_채점결과.xlsx b/회차별채점자료/2601/260128_DIC_2601C_채점결과.xlsx similarity index 100% rename from score_result/260128_DIC_2601C_채점결과.xlsx rename to 회차별채점자료/2601/260128_DIC_2601C_채점결과.xlsx diff --git a/score_result/260128_DPI_2601A_채점결과.xlsx b/회차별채점자료/2601/260128_DPI_2601A_채점결과.xlsx similarity index 100% rename from score_result/260128_DPI_2601A_채점결과.xlsx rename to 회차별채점자료/2601/260128_DPI_2601A_채점결과.xlsx diff --git a/score_result/260128_DPI_2601B_채점결과.xlsx b/회차별채점자료/2601/260128_DPI_2601B_채점결과.xlsx similarity index 100% rename from score_result/260128_DPI_2601B_채점결과.xlsx rename to 회차별채점자료/2601/260128_DPI_2601B_채점결과.xlsx diff --git a/score_result/260129_DIC_2601B_채점결과.xlsx b/회차별채점자료/2601/260129_DIC_2601B_채점결과.xlsx similarity index 100% rename from score_result/260129_DIC_2601B_채점결과.xlsx rename to 회차별채점자료/2601/260129_DIC_2601B_채점결과.xlsx diff --git a/score_result/260129_DIC_2601C_채점결과.xlsx b/회차별채점자료/2601/260129_DIC_2601C_채점결과.xlsx similarity index 100% rename from score_result/260129_DIC_2601C_채점결과.xlsx rename to 회차별채점자료/2601/260129_DIC_2601C_채점결과.xlsx diff --git a/score_result/260129_DPI_2601A_채점결과.xlsx b/회차별채점자료/2601/260129_DPI_2601A_채점결과.xlsx similarity index 100% rename from score_result/260129_DPI_2601A_채점결과.xlsx rename to 회차별채점자료/2601/260129_DPI_2601A_채점결과.xlsx diff --git a/score_result/260129_DPI_2601B_채점결과.xlsx b/회차별채점자료/2601/260129_DPI_2601B_채점결과.xlsx similarity index 100% rename from score_result/260129_DPI_2601B_채점결과.xlsx rename to 회차별채점자료/2601/260129_DPI_2601B_채점결과.xlsx diff --git a/회차별채점자료/2622/제2622회 디지털정보활용능력 멀티미디어제작(곰픽) A형 채점기준표.xlsx b/회차별채점자료/2622/제2622회 디지털정보활용능력 멀티미디어제작(곰픽) A형 채점기준표.xlsx index 4241e82..5d95534 100644 Binary files a/회차별채점자료/2622/제2622회 디지털정보활용능력 멀티미디어제작(곰픽) A형 채점기준표.xlsx and b/회차별채점자료/2622/제2622회 디지털정보활용능력 멀티미디어제작(곰픽) A형 채점기준표.xlsx differ