DPI 1-4문항 레이어명 불일치시 "확인필요"로 처리
This commit is contained in:
@@ -76,7 +76,7 @@ if __name__ == "__main__":
|
|||||||
exam_round = "2622"
|
exam_round = "2622"
|
||||||
exam_codes = ["DIC", "DPI"]
|
exam_codes = ["DIC", "DPI"]
|
||||||
# exam_codes = ["DIC"]
|
# exam_codes = ["DIC"]
|
||||||
source_dir = r"D:\project\GOM\DIC\회차별채점자료\2622"
|
# source_dir = r"D:\project\GOM\DIC\회차별채점자료\2622"
|
||||||
# source_dir = r"D:\project\data\제2522회 특별\(추가)과목별_답안파일"
|
source_dir = r"D:\project\data\제2622회 특별\과목별답안파일 (2)"
|
||||||
|
|
||||||
copy_exam_files(exam_round, exam_codes, source_dir)
|
copy_exam_files(exam_round, exam_codes, source_dir)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const stringSimilarity = require("string-similarity");
|
|||||||
* @param {number} threshold - 유사도 기준 (0~1)
|
* @param {number} threshold - 유사도 기준 (0~1)
|
||||||
* @returns {string} - 유사한 문자열
|
* @returns {string} - 유사한 문자열
|
||||||
*/
|
*/
|
||||||
function findSimilarString(xmlDoc, targetString, threshold = 0.8) {
|
function findSimilarString(xmlDoc, targetString, threshold = 0.7) {
|
||||||
// XML 내부의 비교 대상 텍스트 리스트 찾기
|
// XML 내부의 비교 대상 텍스트 리스트 찾기
|
||||||
function getTextNodes(xmlDoc, paths = ["//CRCUnitArr/@Name"]) {
|
function getTextNodes(xmlDoc, paths = ["//CRCUnitArr/@Name"]) {
|
||||||
const stringList = [];
|
const stringList = [];
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ function getGpdpScore(gpdpData, scoringJson, index) {
|
|||||||
* > 멀티라인 텍스트 유사도 판별하기 어려움
|
* > 멀티라인 텍스트 유사도 판별하기 어려움
|
||||||
*/
|
*/
|
||||||
if (search !== undefined) {
|
if (search !== undefined) {
|
||||||
let result = findSimilarString(gpdpXmlDoc, search, 0.8);
|
let result = findSimilarString(gpdpXmlDoc, search, 0.7);
|
||||||
if (result !== null) {
|
if (result !== null) {
|
||||||
result = result.replace(/"/g, "'");
|
result = result.replace(/"/g, "'");
|
||||||
search = result;
|
search = result;
|
||||||
@@ -202,6 +202,11 @@ function getGpdpScore(gpdpData, scoringJson, index) {
|
|||||||
|
|
||||||
// [1-4] 사진1 > 조정
|
// [1-4] 사진1 > 조정
|
||||||
else if (type === "layer.Effects") {
|
else if (type === "layer.Effects") {
|
||||||
|
if (!ele) {
|
||||||
|
scoringResult[key] = '확인필요';
|
||||||
|
console.log("❌ 오답: 레이어명 확인 필요");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const effects = ele ? xpath.select(ele, gpdpXmlDoc) : [];
|
const effects = ele ? xpath.select(ele, gpdpXmlDoc) : [];
|
||||||
|
|
||||||
let isMatched = false;
|
let isMatched = false;
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ const todayDate = getToday();
|
|||||||
const examRound = '2622';
|
const examRound = '2622';
|
||||||
|
|
||||||
const codeTypes = [
|
const codeTypes = [
|
||||||
'DIC',
|
// 'DIC',
|
||||||
'DPI',
|
'DPI',
|
||||||
];
|
];
|
||||||
|
|
||||||
const examTypes = [
|
const examTypes = [
|
||||||
'A',
|
'A',
|
||||||
'B',
|
// 'B',
|
||||||
'C',
|
// 'C',
|
||||||
// 'D'
|
// 'D'
|
||||||
];
|
];
|
||||||
|
|
||||||
// testMode가 true일 경우 TEST 폴더에 있는 답안 파일을 읽어옴
|
// testMode가 true일 경우 TEST 폴더에 있는 답안 파일을 읽어옴
|
||||||
const testMode = false;
|
// const testMode = false;
|
||||||
// const testMode = true;
|
const testMode = true;
|
||||||
|
|
||||||
const outputExcelFiles = [];
|
const outputExcelFiles = [];
|
||||||
codeTypes.forEach(codeType => {
|
codeTypes.forEach(codeType => {
|
||||||
@@ -36,9 +36,15 @@ codeTypes.forEach(codeType => {
|
|||||||
if (!fs.existsSync(jsonPath)) return
|
if (!fs.existsSync(jsonPath)) return
|
||||||
const scoringJson = require(jsonPath);
|
const scoringJson = require(jsonPath);
|
||||||
const answerFilesDir = `./output/${examRound}/${type}/${testMode ? 'TEST' : codeType}`;
|
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) {
|
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);
|
console.error(`Error reading PSD file: ${psdPath}`, error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 기존 XML 파일 채점 방식 주석 처리 (20260213)
|
||||||
gpdpFiles.forEach((gpdpFile, index) => {
|
gpdpFiles.forEach((gpdpFile, index) => {
|
||||||
const gpdpPath = path.join('./', studentDir, gpdpFile);
|
const gpdpPath = path.join('./', studentDir, gpdpFile);
|
||||||
console.log(`Reading ${gpdpPath}...`);
|
console.log(`Reading ${gpdpPath}...`);
|
||||||
|
|
||||||
const xmlString = fs.readFileSync(gpdpPath, 'utf8');
|
const xmlString = fs.readFileSync(gpdpPath, 'utf8');
|
||||||
// XML 문자열을 파싱하여 XML 문서 객체로 변환
|
|
||||||
const xmlDocument = new DOMParser().parseFromString(xmlString, 'application/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) {
|
if (gmepFile.length === 0) {
|
||||||
// 곰믹스 채점 항목 갯수
|
// 곰믹스 채점 항목 갯수
|
||||||
const gmepItemCount = Object.keys(scoringJson[2]).length;
|
const gmepItemCount = Object.keys(scoringJson[2]).length;
|
||||||
@@ -139,6 +187,10 @@ codeTypes.forEach(codeType => {
|
|||||||
const workbook = XLSX.utils.book_new();
|
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 columnWidths = Object.keys(transposedData[0]).map(key => {
|
||||||
// 각 열의 최대 길이를 계산
|
// 각 열의 최대 길이를 계산
|
||||||
const maxLength = Math.max(
|
const maxLength = Math.max(
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
score_result/2622/260213_DIC_2622B_채점결과.xlsx
Normal file
BIN
score_result/2622/260213_DIC_2622B_채점결과.xlsx
Normal file
Binary file not shown.
BIN
score_result/2622/260213_DPI_2622A_채점결과.xlsx
Normal file
BIN
score_result/2622/260213_DPI_2622A_채점결과.xlsx
Normal file
Binary file not shown.
BIN
score_result/2622/260213_DPI_2622B_채점결과.xlsx
Normal file
BIN
score_result/2622/260213_DPI_2622B_채점결과.xlsx
Normal file
Binary file not shown.
BIN
score_result/2622/260213_DPI_2622C_채점결과.xlsx
Normal file
BIN
score_result/2622/260213_DPI_2622C_채점결과.xlsx
Normal file
Binary file not shown.
BIN
score_result/2622/260219_DPI_2622A_채점결과.xlsx
Normal file
BIN
score_result/2622/260219_DPI_2622A_채점결과.xlsx
Normal file
Binary file not shown.
BIN
score_result/2622/260219_DPI_2622B_채점결과.xlsx
Normal file
BIN
score_result/2622/260219_DPI_2622B_채점결과.xlsx
Normal file
Binary file not shown.
BIN
score_result/2622/260219_DPI_2622C_채점결과.xlsx
Normal file
BIN
score_result/2622/260219_DPI_2622C_채점결과.xlsx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user