프로젝트 파일들 커밋
This commit is contained in:
18
.vscode/launch.json
vendored
Normal file
18
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}/psdExport.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
35
copyFiles.py
Normal file
35
copyFiles.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import os
|
||||
import shutil
|
||||
import unicodedata
|
||||
|
||||
def copy_dic_subdirs(source_root, target_root_b, target_root_c):
|
||||
for root, dirs, files in os.walk(source_root):
|
||||
for dir_name in dirs:
|
||||
if dir_name == 'DIC': # DIC 디렉토리 탐색
|
||||
parent_dir = os.path.basename(os.path.dirname(os.path.join(root, dir_name)))
|
||||
target_root = None
|
||||
parent_dir = unicodedata.normalize('NFC', parent_dir)
|
||||
|
||||
# 부모 디렉토리가 '2교시'인지, '3교시'인지 확인
|
||||
if parent_dir == '2교시':
|
||||
target_root = target_root_b
|
||||
elif parent_dir == '3교시':
|
||||
target_root = target_root_c
|
||||
|
||||
if target_root:
|
||||
source_dic_path = os.path.join(root, dir_name)
|
||||
target_dic_path = os.path.join(target_root, dir_name)
|
||||
|
||||
# DIC 하위 디렉토리와 파일 복사
|
||||
shutil.copytree(source_dic_path, target_dic_path, dirs_exist_ok=True)
|
||||
print(f"Copied {source_dic_path} to {target_dic_path}")
|
||||
|
||||
else:
|
||||
print(f"Skipping {dir_name} under {parent_dir}, as it doesn't match '2교시' or '3교시'.")
|
||||
|
||||
# 사용법
|
||||
source_directory = "/Users/waterdrw/Nextcloud/Development/KAIT/검정데이터/제2501회 정기/답안파일/제2501회 디지털정보활용능력_정기_답안파일/" # 원본 디렉토리 경로
|
||||
target_directory_b = "./output/B" # '2교시'의 타겟 경로
|
||||
target_directory_c = "./output/C" # '3교시'의 타겟 경로
|
||||
|
||||
copy_dic_subdirs(source_directory, target_directory_b, target_directory_c)
|
||||
BIN
output.xlsx
Normal file
BIN
output.xlsx
Normal file
Binary file not shown.
13
package.json
Normal file
13
package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "psd-test",
|
||||
"version": "1.0.0",
|
||||
"description": "### psdExxport.js nodejs 기반, scoring.json 파일에 채점기준표 만들어서 채점",
|
||||
"main": "psdExport.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node psdExport.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
376
psdExport.js
Normal file
376
psdExport.js
Normal file
@@ -0,0 +1,376 @@
|
||||
const jsonPath = require('jsonpath');
|
||||
const XLSX = require('xlsx');
|
||||
const psd = require('psd');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const xpath = require('xpath');
|
||||
const { DOMParser } = require('xmldom');
|
||||
|
||||
|
||||
const sampleDir = './output/C/DIC';
|
||||
const students = fs.readdirSync(sampleDir);
|
||||
|
||||
// 기준표 파일 읽기
|
||||
const scoring = require('./scoring.json');
|
||||
|
||||
const psdData = [];
|
||||
const gradingResults = [];
|
||||
|
||||
students.forEach(student => {
|
||||
// 맥에서 한글 디렉토리 이름을 읽어서 엑셀에 저장 할 시 자소 분리가 되어 저장되는 문제 노말라이즈해서 해결
|
||||
const name = student.normalize('NFC');
|
||||
const studentDir = path.join(sampleDir, student);
|
||||
const psdFiles = fs.readdirSync(studentDir).filter(file => file.endsWith('.psd'));
|
||||
const gmepFile = fs.readdirSync(studentDir).filter(file => file.endsWith('.gmep'));
|
||||
|
||||
// 학생 이름을 key로 하는 객체 생성
|
||||
const gradingResult = {
|
||||
0: name
|
||||
};
|
||||
|
||||
psdFiles.forEach((psdFile, index) => {
|
||||
const psdPath = path.join('./', studentDir, psdFile);
|
||||
console.log(`Reading ${psdPath}...`);
|
||||
psdData[index] = psd.fromFile(psdPath);
|
||||
psdData[index].parse();
|
||||
gradingResult[index + 1] = getScore(psdData, scoring, index);
|
||||
});
|
||||
gmepFile.forEach((gmep, index) => {
|
||||
const gmepPath = path.join('./', studentDir, gmep);
|
||||
console.log(`Reading ${gmepPath}...`);
|
||||
const xmlContent = fs.readFileSync(gmepPath, 'utf8');
|
||||
// XML 파싱
|
||||
const doc = new DOMParser().parseFromString(xmlContent, 'application/xml');
|
||||
// console.log('doc:', doc);
|
||||
|
||||
gradingResult[3] = getGmepScore(doc, scoring, 2);
|
||||
});
|
||||
gradingResults.push(gradingResult);
|
||||
});
|
||||
|
||||
// 엑셀 파일 생성
|
||||
|
||||
// Flatten the resultData for better representation in Excel
|
||||
const flattenedData = gradingResults.map(student => {
|
||||
const name = student["0"]
|
||||
const flattened = { "학생": student["0"] };
|
||||
Object.keys(student).forEach(key => {
|
||||
if (key !== "0") {
|
||||
Object.keys(student[key]).forEach(subKey => {
|
||||
flattened[`${key}_${subKey}`] = student[key][subKey];
|
||||
});
|
||||
}
|
||||
});
|
||||
return flattened;
|
||||
});
|
||||
// console.log(flattenedData);
|
||||
|
||||
const worksheet = XLSX.utils.json_to_sheet(flattenedData);
|
||||
const workbook = XLSX.utils.book_new();
|
||||
|
||||
// Add the worksheet to the workbook
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, '채점 결과');
|
||||
|
||||
// 엑셀 파일 저장
|
||||
XLSX.writeFile(workbook, 'output.xlsx');
|
||||
console.log('채점 결과가 output.xlsx 파일에 저장되었습니다.');
|
||||
|
||||
|
||||
// xml 형식의 gmep 파일을 읽어서 점수를 계산
|
||||
// scoring.json 파일 내에 있는 ele 요소는 xmlpath 형식으로 접근하여 요소를 탐색하고 나오는 값을 value와 비교하여 점수를 계산
|
||||
// scoring.json 파일 내에 있는 type은 비교할 값의 타입을 의미하며, boolean, array 등이 있음
|
||||
// scoring.json 파일 내에 있는 type에 따라 비교하는 방식이 달라짐
|
||||
// 채점 결과를 gradingResults 배열에 저장
|
||||
function getGmepScore(gmepData, scoring, index) {
|
||||
const doc = gmepData;
|
||||
const gradingResult = {};
|
||||
|
||||
const scoringData = scoring[index];
|
||||
// console.log(scoringData);
|
||||
|
||||
let totalScore = 0;
|
||||
for (const key in scoringData) {
|
||||
const ele = scoringData[key].ele;
|
||||
const value = scoringData[key].value;
|
||||
const point = scoringData[key].point;
|
||||
const type = scoringData[key].type;
|
||||
|
||||
if (ele === 'none') {
|
||||
gradingResult[key] = "확인필요";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "boolean") {
|
||||
gradingResult[key] = result.length > 0 ? point : 0;
|
||||
}
|
||||
else if (type == "array") {
|
||||
// result: Path="동영상.mp4", Path="음악.mp3", Path="이미지2.jpg", Path="이미지1.jpg"
|
||||
// value: 동영상.mp4,이미지1.jpg,이미지3.jpg,이미지2.jpg
|
||||
// result 와 value를 순서대로 비교하여 모두 같으면 점수 point 부여
|
||||
|
||||
// XPath를 사용하여 CRTrackList Name="비디오1" 요소 찾기
|
||||
const trackListNode = xpath.select1('//CRVideoTrackArr/CRTrackList[@Name="비디오1"]', doc);
|
||||
const values = [];
|
||||
let isSame = true;
|
||||
|
||||
if (trackListNode) {
|
||||
// CRTrackClip 요소의 ClipIndex를 참조하여 CRClip 요소의 Path와 Type 출력
|
||||
const clipIndexes = xpath.select('CRTrackClip/@ClipIndex', trackListNode);
|
||||
clipIndexes.forEach(indexNode => {
|
||||
const clipIndex = parseInt(indexNode.value, 10) + 1; // XPath는 1-based index를 사용
|
||||
console.log(`clipIndex: ${clipIndex}`);
|
||||
if (clipIndex === 0) {
|
||||
return;
|
||||
}
|
||||
const clipPathNode = xpath.select1(`//CRClipArr/CRClip[${clipIndex}]/@Path`, doc);
|
||||
|
||||
if (clipPathNode === undefined) {
|
||||
console.log(`clipPathNode: undefined`);
|
||||
return;
|
||||
}
|
||||
console.log(`clipPathNode: ${clipPathNode.value}`);
|
||||
values.push(clipPathNode.value);
|
||||
});
|
||||
// values에 값이 있는지 확인
|
||||
if (values.length == 0) {
|
||||
console.log('values length 0');
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
values.forEach((v, i) => {
|
||||
console.log(`values: ${v} value: ${value[i]}`);
|
||||
if (value[i] !== v) {
|
||||
isSame = false;
|
||||
}
|
||||
});
|
||||
totalScore += isSame ? point : 0;
|
||||
gradingResult[key] = isSame ? point : 0;
|
||||
} else {
|
||||
console.log('CRTrackList with Name="비디오1" not found.');
|
||||
gradingResult[key] = 0;
|
||||
}
|
||||
}
|
||||
else if (type == "startend") {
|
||||
console.log('type:', type);
|
||||
const start = scoringData[key].start;
|
||||
const end = scoringData[key].end;
|
||||
// XPath를 사용하여 CRClip 요소 중 Path가 '동영상.mp4'인 요소의 위치 찾기
|
||||
const clipIndexNode = xpath.select1(ele, doc);
|
||||
console.log(`clipIndexNode: ${clipIndexNode}`);
|
||||
|
||||
// XPath를 사용하여 해당 ClipIndex를 사용하는 CRTrackClip 요소 찾기
|
||||
const trackClipNodes = xpath.select1(`//CRTrackClip[@ClipIndex='${clipIndexNode}']`, doc);
|
||||
|
||||
if (!trackClipNodes) {
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
const posNode = xpath.select1('@Pos', trackClipNodes);
|
||||
const lengthNode = xpath.select1('@Length', trackClipNodes);
|
||||
console.log(`Pos: ${posNode.value}, Length: ${lengthNode.value}`);
|
||||
|
||||
gradingResult[key] = posNode.value === start && lengthNode.value === end ? point : 0;
|
||||
totalScore += posNode.value === start && lengthNode.value === end ? point : 0;
|
||||
|
||||
}
|
||||
else if (type == "subtitle") {
|
||||
const result = xpath.select(ele, doc);
|
||||
const length = scoringData[key].length;
|
||||
// 결과는 배열로 나오는데 2개 일 경우가 있음
|
||||
|
||||
if (result.length !== length) {
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
gradingResult[key] = point;
|
||||
totalScore += point;
|
||||
}
|
||||
else if (type == "color") {
|
||||
const result = xpath.select(ele, doc);
|
||||
|
||||
if (result.length == 0) {
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(`value: ${value} result: ${result[0].value}`);
|
||||
// value와 result[0].value를 비교하여 같으면 점수 point 부여
|
||||
totalScore += result.length > 0 && value === result[0].value ? point : 0;
|
||||
gradingResult[key] = result.length > 0 && value === result[0].value ? point : 0;
|
||||
|
||||
}
|
||||
else if (type == "multi") {
|
||||
try {
|
||||
const result = xpath.select(ele, doc);
|
||||
let isSame = true;
|
||||
// console.log(`ele: ${ele}, value: ${value} result: ${result}`);
|
||||
|
||||
if (result.length == 0) {
|
||||
console.log('result length 0');
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
result.forEach((v, i) => {
|
||||
// value[i] 값이 정수형인 경우에는 float로 변환하여 비교
|
||||
// 정수형 v값을 float 형으로 변환하고 소수점 3자리까지 버림
|
||||
let temp = v.value;
|
||||
let answer = value[i];
|
||||
|
||||
if (Number.isFinite(value[i]) && !Number.isInteger(value[i])) {
|
||||
temp = parseFloat(v.value);
|
||||
answer = parseFloat(value[i]);
|
||||
// 소수점 3자리까지 버림
|
||||
temp = Math.floor(temp * 1000) / 1000;
|
||||
}
|
||||
// answer 문자열 중 : 가 포함되어 있다면 각각 분리하고 그 값의 차이를 구함
|
||||
if (typeof answer == "string" && answer.indexOf(':') > -1) {
|
||||
const [answerStart, answerEnd] = answer.split(':').map(Number);
|
||||
const [tempStart, tempEnd] = temp.split(':').map(Number);
|
||||
answer = answerEnd - answerStart;
|
||||
temp = tempEnd - tempStart;
|
||||
}
|
||||
|
||||
console.log(`temp: ${temp} answer: ${answer}`);
|
||||
if (answer !== temp) {
|
||||
console.log(`answer !== temp`);
|
||||
isSame = false;
|
||||
}
|
||||
});
|
||||
totalScore += isSame ? point : 0;
|
||||
gradingResult[key] = isSame ? point : 0;
|
||||
} catch (e) {
|
||||
console.log('err :', e);
|
||||
gradingResult[key] = 0;
|
||||
}
|
||||
}
|
||||
else if (type == "searchIndex") {
|
||||
let existEle = scoringData[key].existEle;
|
||||
// XPath를 사용하여 ELE 요소가 존재하는지 확인
|
||||
const crcUnitArrNode = xpath.select1(existEle, doc);
|
||||
|
||||
if (crcUnitArrNode) {
|
||||
// ELE 요소가 몇번째 요소인지 찾고 필요한 요소 확인
|
||||
const unitOrderNode = xpath.select1(ele, doc);
|
||||
console.log(`unitOrderNode: ${unitOrderNode}`);
|
||||
if (unitOrderNode === undefined) {
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
if (unitOrderNode.value === value) {
|
||||
console.log(`${unitOrderNode.value} === ${value}`);
|
||||
gradingResult[key] = point;
|
||||
totalScore += point;
|
||||
}
|
||||
else if (unitOrderNode === value) {
|
||||
console.log(`${unitOrderNode} === ${value}`);
|
||||
gradingResult[key] = point;
|
||||
totalScore += point;
|
||||
}
|
||||
else {
|
||||
gradingResult[key] = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
console.log(`not found. ${existEle} `);
|
||||
gradingResult[key] = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('Unknown type:', type);
|
||||
const result = xpath.select(ele, doc);
|
||||
|
||||
if (result.length == 0) {
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
// console.log(`result: ${result[0].value}`);
|
||||
// value와 result[0].value를 비교하여 같으면 점수 point 부여
|
||||
totalScore += result.length > 0 && value === result[0].value ? point : 0;
|
||||
gradingResult[key] = result.length > 0 && value === result[0].value ? point : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gradingResult['총점'] = totalScore;
|
||||
return gradingResult;
|
||||
}
|
||||
|
||||
|
||||
// psdData를 scoring.json 파일 내에 있는 ele 요소의 jsonpath로 접근하여 요소를 탐색하고 나오는 값을 value와 비교하여 점수를 계산
|
||||
// 학생 별로 psdData는 2개씩 있으므로 PSD 파일 1번과 2번에 대해서 채점
|
||||
// scoring.json 파일에 있는 항목 수만큼 점수를 계산
|
||||
// scoring.json 파일의 1번째 배열은 PSD 파일 1번에 대한 점수 계산
|
||||
// scoring.json 파일의 2번째 배열은 PSD 파일 2번에 대한 점수 계산
|
||||
// 채점 결과를 gradingResults 배열에 저장
|
||||
function getScore(psdData, scoring, index) {
|
||||
const psdTree = psdData[index].tree().export();
|
||||
const jsonData = JSON.stringify(psdTree, null, 2);
|
||||
// console.log(jsonData);
|
||||
const gradingResult = {};
|
||||
|
||||
const scoringData = scoring[index];
|
||||
let totalScore = 0;
|
||||
for (const key in scoringData) {
|
||||
const ele = scoringData[key].ele;
|
||||
const value = scoringData[key].value;
|
||||
const point = scoringData[key].point;
|
||||
const type = scoringData[key].type;
|
||||
|
||||
if (ele === 'none') {
|
||||
gradingResult[key] = "확인필요";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const result = jsonPath.query(psdTree, ele);
|
||||
console.log(`ele: ${ele}, value: ${value} result: ${result}`);
|
||||
if (result.length == 0) {
|
||||
gradingResult[key] = 0;
|
||||
continue;
|
||||
}
|
||||
if (type == "boolean") {
|
||||
// console.log(`result ${result.length}`);
|
||||
|
||||
gradingResult[key] = result.length > 0 ? point : 0;
|
||||
}
|
||||
// value가 color code인 경우 R,G,B를 16진수로 변환하여 비교하고 같다면 점수 부여
|
||||
// value: "ffa200"
|
||||
// result: [255,162,0,255]
|
||||
// 255,162,0,255 -> ffa200
|
||||
else if (type == "color") {
|
||||
// console.log(`result ${result}`); // result 255,162,0,255
|
||||
const temp = result[0].slice(0, 3).join(','); // 255,162,0
|
||||
color = temp.split(',').map(v => parseInt(v).toString(16)).join(''); // ffa20
|
||||
// ffa20 -> ffa200
|
||||
if (color.length == 5) {
|
||||
color = color + '0';
|
||||
}
|
||||
|
||||
// console.log(`color: ${color}`);
|
||||
gradingResult[key] = result.length > 0 && value === color ? point : 0;
|
||||
}
|
||||
|
||||
|
||||
// type이 font인 경우 font의 이름만 추출하여 비교
|
||||
// value: "Arial"
|
||||
// result: ["Arial-BoldItalicMT"]
|
||||
else if (type == "font") {
|
||||
// console.log(`result ${result}`);
|
||||
const font = result[0].split('-')[0];
|
||||
// console.log(`font: ${font}`);
|
||||
gradingResult[key] = result.length > 0 && value === font ? point : 0;
|
||||
}
|
||||
|
||||
else if (result[0] === value) {
|
||||
gradingResult[key] = point;
|
||||
totalScore += point;
|
||||
} else {
|
||||
gradingResult[key] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
gradingResult['총점'] = totalScore;
|
||||
return gradingResult;
|
||||
}
|
||||
230
psdTree.json
Normal file
230
psdTree.json
Normal file
@@ -0,0 +1,230 @@
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"type": "layer",
|
||||
"visible": true,
|
||||
"opacity": 1,
|
||||
"blendingMode": "normal",
|
||||
"name": "강아지",
|
||||
"left": 47,
|
||||
"right": 62,
|
||||
"top": 14,
|
||||
"bottom": 34,
|
||||
"height": 20,
|
||||
"width": 15,
|
||||
"mask": {},
|
||||
"image": {}
|
||||
},
|
||||
{
|
||||
"type": "layer",
|
||||
"visible": true,
|
||||
"opacity": 1,
|
||||
"blendingMode": "normal",
|
||||
"name": "동네 친구들",
|
||||
"left": 42,
|
||||
"right": 63,
|
||||
"top": 8,
|
||||
"bottom": 13,
|
||||
"height": 5,
|
||||
"width": 21,
|
||||
"mask": {},
|
||||
"text": {
|
||||
"value": "동네 친구들",
|
||||
"font": {
|
||||
"lengthArray": [
|
||||
1,
|
||||
5
|
||||
],
|
||||
"styles": [
|
||||
"normal",
|
||||
"normal"
|
||||
],
|
||||
"weights": [
|
||||
"normal",
|
||||
"normal"
|
||||
],
|
||||
"names": [
|
||||
"GungsuhChe",
|
||||
"Gulim",
|
||||
"AdobeInvisFont"
|
||||
],
|
||||
"sizes": [
|
||||
36,
|
||||
36
|
||||
],
|
||||
"colors": [
|
||||
[
|
||||
39,
|
||||
214,
|
||||
220,
|
||||
255
|
||||
],
|
||||
[
|
||||
39,
|
||||
214,
|
||||
220,
|
||||
255
|
||||
]
|
||||
],
|
||||
"alignment": [
|
||||
"left"
|
||||
],
|
||||
"textDecoration": [
|
||||
"none",
|
||||
"none"
|
||||
],
|
||||
"leading": [
|
||||
57.6,
|
||||
57.6
|
||||
]
|
||||
},
|
||||
"left": 0,
|
||||
"top": 0,
|
||||
"right": 0,
|
||||
"bottom": 0,
|
||||
"transform": {
|
||||
"xx": 0.1,
|
||||
"xy": 0,
|
||||
"yx": 0,
|
||||
"yy": 0.09999999999999999,
|
||||
"tx": 42.800000000000004,
|
||||
"ty": 11.7
|
||||
}
|
||||
},
|
||||
"image": {}
|
||||
},
|
||||
{
|
||||
"type": "layer",
|
||||
"visible": true,
|
||||
"opacity": 1,
|
||||
"blendingMode": "normal",
|
||||
"name": "Neighborhood Friends",
|
||||
"left": 11,
|
||||
"right": 63,
|
||||
"top": 2,
|
||||
"bottom": 8,
|
||||
"height": 6,
|
||||
"width": 52,
|
||||
"mask": {},
|
||||
"text": {
|
||||
"value": "Neighborhood Friends",
|
||||
"font": {
|
||||
"lengthArray": [
|
||||
20
|
||||
],
|
||||
"styles": [
|
||||
"normal"
|
||||
],
|
||||
"weights": [
|
||||
"normal"
|
||||
],
|
||||
"names": [
|
||||
"Arial-BoldItalicMT",
|
||||
"Gulim",
|
||||
"AdobeInvisFont"
|
||||
],
|
||||
"sizes": [
|
||||
48
|
||||
],
|
||||
"colors": [
|
||||
[
|
||||
255,
|
||||
162,
|
||||
0,
|
||||
255
|
||||
]
|
||||
],
|
||||
"alignment": [
|
||||
"left"
|
||||
],
|
||||
"textDecoration": [
|
||||
"none"
|
||||
],
|
||||
"leading": [
|
||||
43.2
|
||||
]
|
||||
},
|
||||
"left": 0,
|
||||
"top": 0,
|
||||
"right": 0,
|
||||
"bottom": 0,
|
||||
"transform": {
|
||||
"xx": 0.1,
|
||||
"xy": 0,
|
||||
"yx": 0,
|
||||
"yy": 0.09999999999999999,
|
||||
"tx": 11.100000000000001,
|
||||
"ty": 6.3
|
||||
}
|
||||
},
|
||||
"image": {}
|
||||
},
|
||||
{
|
||||
"type": "layer",
|
||||
"visible": true,
|
||||
"opacity": 1,
|
||||
"blendingMode": "normal",
|
||||
"name": "동네쉼터",
|
||||
"left": 0,
|
||||
"right": 65,
|
||||
"top": 0,
|
||||
"bottom": 35,
|
||||
"height": 35,
|
||||
"width": 65,
|
||||
"mask": {
|
||||
"top": 0,
|
||||
"left": 33,
|
||||
"bottom": 35,
|
||||
"right": 65,
|
||||
"width": 32,
|
||||
"height": 35,
|
||||
"defaultColor": 255,
|
||||
"relative": false,
|
||||
"disabled": false,
|
||||
"invert": false
|
||||
},
|
||||
"image": {}
|
||||
},
|
||||
{
|
||||
"type": "layer",
|
||||
"visible": true,
|
||||
"opacity": 1,
|
||||
"blendingMode": "normal",
|
||||
"name": "Background",
|
||||
"left": 0,
|
||||
"right": 65,
|
||||
"top": 0,
|
||||
"bottom": 35,
|
||||
"height": 35,
|
||||
"width": 65,
|
||||
"mask": {},
|
||||
"image": {}
|
||||
}
|
||||
],
|
||||
"document": {
|
||||
"width": 65,
|
||||
"height": 35,
|
||||
"resources": {
|
||||
"layerComps": [],
|
||||
"resolutionInfo": {
|
||||
"h_res": 72,
|
||||
"h_res_unit": 1,
|
||||
"width_unit": 2,
|
||||
"v_res": 72,
|
||||
"v_res_unit": 1,
|
||||
"height_unit": 2
|
||||
},
|
||||
"guides": [
|
||||
{
|
||||
"location": "29495882.4",
|
||||
"direction": "horizontal"
|
||||
},
|
||||
{
|
||||
"location": "15728640.0",
|
||||
"direction": "vertical"
|
||||
}
|
||||
],
|
||||
"slices": []
|
||||
}
|
||||
}
|
||||
}
|
||||
38
result.json
Normal file
38
result.json
Normal file
@@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"0": "멀티미디어-000000-홍길동",
|
||||
"1": {
|
||||
"1": 10,
|
||||
"총점": 0
|
||||
},
|
||||
"2": {
|
||||
"1": 10,
|
||||
"2": 10,
|
||||
"3": 0,
|
||||
"4": 10,
|
||||
"5": 10,
|
||||
"6": 0,
|
||||
"7": "확인필요",
|
||||
"8": "확인필요",
|
||||
"총점": 30
|
||||
}
|
||||
},
|
||||
{
|
||||
"0": "멀티미디어-001671-박도율",
|
||||
"1": {
|
||||
"1": 10,
|
||||
"총점": 0
|
||||
},
|
||||
"2": {
|
||||
"1": 0,
|
||||
"2": 10,
|
||||
"3": 0,
|
||||
"4": 10,
|
||||
"5": 10,
|
||||
"6": 0,
|
||||
"7": "확인필요",
|
||||
"8": "확인필요",
|
||||
"총점": 30
|
||||
}
|
||||
}
|
||||
]
|
||||
371
scoring.json
Normal file
371
scoring.json
Normal file
@@ -0,0 +1,371 @@
|
||||
{
|
||||
"0": {
|
||||
"1": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"2": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"3": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"4": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"5": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"6": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"7": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"8": {
|
||||
"ele": "$[?(@.width == 65 && @.height == 45)]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"1": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"2": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"3": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"4": {
|
||||
"ele": "$.children[?(@.name=='Amusement Park')]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
},
|
||||
"5": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"6": {
|
||||
"ele": "$.children[?(@.name=='Amusement Park')].name",
|
||||
"value": "Amusement Park",
|
||||
"point": 10
|
||||
},
|
||||
"7": {
|
||||
"ele": "$.children[?(@.name=='Amusement Park')].text.font.names[0]",
|
||||
"type": "font",
|
||||
"value": "Arial",
|
||||
"point": 10
|
||||
},
|
||||
"8": {
|
||||
"ele": "$.children[?(@.name=='Amusement Park')].text.font.names[0]",
|
||||
"value": "Arial-BoldItalicMT",
|
||||
"point": 10
|
||||
},
|
||||
"9": {
|
||||
"ele": "$.children[?(@.name=='Amusement Park')].text.font.sizes[0]",
|
||||
"value": 48,
|
||||
"point": 10
|
||||
},
|
||||
"10": {
|
||||
"ele": "$.children[?(@.name=='Amusement Park')].text.font.colors[0]",
|
||||
"type": "color",
|
||||
"value": "aaaaaa",
|
||||
"point": 10
|
||||
},
|
||||
"11": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"12": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"13": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"14": {
|
||||
"ele": "$.children[?(@.name=='가오슝 놀이공원 가요')].name",
|
||||
"value": "가오슝 놀이공원 가요",
|
||||
"point": 10
|
||||
},
|
||||
"15": {
|
||||
"ele": "$.children[?(@.name=='가오슝 놀이공원 가요')].text.font.names[0]",
|
||||
"type": "font",
|
||||
"value": "DotumChe",
|
||||
"point": 10
|
||||
},
|
||||
"16": {
|
||||
"ele": "$.children[?(@.name=='가오슝 놀이공원 가요')].text.font.sizes[0]",
|
||||
"value": 36,
|
||||
"point": 10
|
||||
},
|
||||
"17": {
|
||||
"ele": "$.children[?(@.name=='가오슝 놀이공원 가요')].text.font.colors[0]",
|
||||
"type": "color",
|
||||
"value": "261795",
|
||||
"point": 10
|
||||
},
|
||||
"18": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"19": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"20": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"21": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"22": {
|
||||
"ele": "$.children[?(@.name=='드롭존')]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
},
|
||||
"23": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"24": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"25": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"26": {
|
||||
"ele": "$[?(@.width == 65 && @.height == 35)]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"1": {
|
||||
"ele": "//CRClipArr/CRClip[position() = //CRTrackList[1]/CRTrackClip/@ClipIndex]/@Path",
|
||||
"type": "array",
|
||||
"value": [
|
||||
"동영상.mp4",
|
||||
"이미지1.jpg",
|
||||
"이미지3.jpg",
|
||||
"이미지2.jpg"
|
||||
],
|
||||
"point": 4
|
||||
},
|
||||
"2": {
|
||||
"ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed",
|
||||
"value": "150",
|
||||
"point": 2
|
||||
},
|
||||
"3": {
|
||||
"ele": "count(//CRClip[@Path='동영상.mp4']/preceding-sibling::*)",
|
||||
"type": "startend",
|
||||
"start": "0",
|
||||
"end": "230",
|
||||
"point": 2
|
||||
},
|
||||
"4": {
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='동영상.mp4']/preceding-sibling::*)]//CRFilter[@ID='43'][@VID100='5'][@VID103='0.89999998']",
|
||||
"point": 3
|
||||
},
|
||||
"5": {
|
||||
"ele": "//GPString[@VID7='재미있는 놀이공원']/@VID7",
|
||||
"type": "subtitle",
|
||||
"length": 1,
|
||||
"point": 3
|
||||
},
|
||||
"6": {
|
||||
"ele": "//CRCUnitArr[@Name='재미있는 놀이공원']//GCUnitPool[@Type='1']/GCUnit[@VID102='바탕체']",
|
||||
"point": 2
|
||||
},
|
||||
"7": {
|
||||
"ele": "//CRCUnitArr[@Name='재미있는 놀이공원']//GCUnitPool[@Type='1']/GCUnit[@VID101='130']",
|
||||
"point": 2
|
||||
},
|
||||
"8": {
|
||||
"ele": "//CRCUnitArr[@Name='재미있는 놀이공원']//GCUnitPool/GCUnit[@Type='4']/@VID100",
|
||||
"type": "color",
|
||||
"value": "-6742488",
|
||||
"point": 2
|
||||
},
|
||||
"9": {
|
||||
"ele": "//CRCUnitArr[@Name='재미있는 놀이공원']/@VID600 | //CRCUnitArr[@Name='재미있는 놀이공원']/@VID601",
|
||||
"type": "multi",
|
||||
"value": [
|
||||
0.291,
|
||||
0.914
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"10": {
|
||||
"existEle": "//CRCUnitArr[@Name='재미있는 놀이공원']",
|
||||
"ele": "sum(//CRTrackList[@Name='텍스트']/CRTrackClip[not(@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='재미있는 놀이공원']]/preceding::CROwneUnit))]/@Length)",
|
||||
"type": "searchIndex",
|
||||
"value": 150,
|
||||
"point": 2
|
||||
},
|
||||
"11": {
|
||||
"existEle": "//CRCUnitArr[@Name='재미있는 놀이공원']",
|
||||
"ele": "//CRTrackList[@Name='텍스트']/CRTrackClip[@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='재미있는 놀이공원']]/preceding::CROwneUnit)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "120",
|
||||
"point": 2
|
||||
},
|
||||
"12": {
|
||||
"existEle": "//CRClip[@Path='동영상.mp4']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='동영상.mp4']/preceding-sibling::*)]/@Mute",
|
||||
"type": "searchIndex",
|
||||
"value": "1",
|
||||
"point": 2
|
||||
},
|
||||
"13": {
|
||||
"existEle": "//CRClip[@Path='이미지1.jpg']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "150",
|
||||
"point": 2
|
||||
},
|
||||
"14": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]//CRFilter/@ID |//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]//CRFilter/@VID100",
|
||||
"value": [
|
||||
"102",
|
||||
"2"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"15": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@ID|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Range|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Type",
|
||||
"value": [
|
||||
"11",
|
||||
"320:380",
|
||||
"2"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"16": {
|
||||
"existEle": "//CRClip[@Path='이미지3.jpg']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "180",
|
||||
"point": 2
|
||||
},
|
||||
"17": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]//CRFilter/@ID |//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]//CRFilter/@VID101",
|
||||
"value": [
|
||||
"103",
|
||||
"10"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"18": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@ID|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Range|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Type",
|
||||
"value": [
|
||||
"8",
|
||||
"500:560",
|
||||
"2"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"19": {
|
||||
"existEle": "//CRClip[@Path='이미지2.jpg']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "180",
|
||||
"point": 2
|
||||
},
|
||||
"20": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]//CRFilter/@ID |//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]//CRFilter/@VID100",
|
||||
"value": [
|
||||
"67",
|
||||
"4"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"21": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@ID|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Range|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Type",
|
||||
"value": [
|
||||
"19",
|
||||
"710:740",
|
||||
"2"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"22": {
|
||||
"ele": "//GPString[@VID7='자동차 레이싱 코스' or @VID7='(A Car Racing Course)']/@VID7",
|
||||
"type": "subtitle",
|
||||
"length": 2,
|
||||
"point": 3
|
||||
},
|
||||
"23": {
|
||||
"ele": "//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)']//GCUnitPool[@Type='1']/GCUnit[@VID102='돋움체']",
|
||||
"point": 2
|
||||
},
|
||||
"24": {
|
||||
"ele": "//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)']//GCUnitPool[@Type='1']/GCUnit[@VID101='150']",
|
||||
"point": 2
|
||||
},
|
||||
"25": {
|
||||
"ele": "//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)']//GCUnitPool/GCUnit[@Type='4']/@VID100",
|
||||
"type": "color",
|
||||
"value": "-8036654",
|
||||
"point": 2
|
||||
},
|
||||
"26": {
|
||||
"ele": "//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)']//GCUnitPool/GCUnit[@Type='2'][@VID100='0.30000001'][@VID101='-16777216']",
|
||||
"point": 2
|
||||
},
|
||||
"27": {
|
||||
"ele": "//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)'][@VID505='1'][@VID507='2']",
|
||||
"point": 3
|
||||
},
|
||||
"28": {
|
||||
"existEle": "//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)']",
|
||||
"ele": "//CRTrackList[@Name='텍스트']/CRTrackClip[@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='재미있는 놀이공원']]/preceding::CROwneUnit)]/@Pos",
|
||||
"type": "searchIndex",
|
||||
"value": "0",
|
||||
"point": 2
|
||||
},
|
||||
"29": {
|
||||
"existEle": "//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)']",
|
||||
"ele": "//CRTrackList[@Name='텍스트']/CRTrackClip[(@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='자동차 레이싱 코스 (A Car Racing Course)']]/preceding::CROwneUnit))]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "120",
|
||||
"point": 2
|
||||
},
|
||||
"30":{
|
||||
"ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']/CRTrackClip[@Pos='0']",
|
||||
"point": 2
|
||||
},
|
||||
"31":{
|
||||
"ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']/CRTrackClip[@Length='720']",
|
||||
"point": 2
|
||||
},
|
||||
"32":{
|
||||
"ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']//CRFilter[@Type='2'][@ID='1'][@VID8='90']",
|
||||
"point": 2
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
43
test.py
Normal file
43
test.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from psd_tools import PSDImage
|
||||
|
||||
psd = PSDImage.open('./sample/dic_02_000000_홍길동.psd')
|
||||
|
||||
def print_layer_info(layer, indent=0):
|
||||
prefix = ' ' * indent
|
||||
# print(f"{prefix}Layer: {layer.name}")
|
||||
# print(f"{prefix} Type: {layer.kind}")
|
||||
# print(f"{prefix} Visible: {layer.visible}")
|
||||
# print(f"{prefix} Opacity: {layer.opacity}")
|
||||
# print(f"{prefix} Blending Mode: {layer.blending_mode}")
|
||||
# print(f"{prefix} Bounds: {layer.bbox}")
|
||||
|
||||
if layer.kind == 'pixel':
|
||||
print(f"{prefix} Pixel Data: {layer.topil()}")
|
||||
elif layer.kind == 'type':
|
||||
# print(layer.text)
|
||||
# print(layer.engine_dict['StyleRun'])
|
||||
|
||||
# # Extract font for each substring in the text.
|
||||
text = layer.engine_dict['Editor']['Text'].value
|
||||
print(f"text: {text}")
|
||||
fontset = layer.resource_dict['FontSet']
|
||||
print(fontset)
|
||||
runlength = layer.engine_dict['StyleRun']['RunLengthArray']
|
||||
rundata = layer.engine_dict['StyleRun']['RunArray']
|
||||
print(rundata)
|
||||
|
||||
|
||||
|
||||
# index = 0
|
||||
# for length, style in zip(runlength, rundata):
|
||||
# substring = text[index:index + length]
|
||||
# stylesheet = style['StyleSheet']['StyleSheetData']
|
||||
# font = fontset[stylesheet['Font']]
|
||||
# # print('%r gets %s' % (substring, font))
|
||||
# index += length
|
||||
|
||||
for layer in psd:
|
||||
print_layer_info(layer)
|
||||
if layer.is_group():
|
||||
for child in layer:
|
||||
print_layer_info(child, indent=2)
|
||||
24
xpathTest.js
Normal file
24
xpathTest.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const fs = require('fs');
|
||||
const xpath = require('xpath');
|
||||
const { DOMParser } = require('xmldom');
|
||||
|
||||
// XML 파일 읽기
|
||||
const xmlFilePath = '/Users/waterdrw/Works/KAIT/psd-test/sample/dic_03_000000_홍길동/dic_03_000000_홍길동.gmep';
|
||||
const xmlContent = fs.readFileSync(xmlFilePath, 'utf8');
|
||||
|
||||
// XML 파싱
|
||||
const doc = new DOMParser().parseFromString(xmlContent, 'application/xml');
|
||||
|
||||
// XPath를 사용하여 CRCUnitArr Name="추억의 말뚝박기 놀이" 요소가 존재하는지 확인
|
||||
const crcUnitArrNode = xpath.select1('//CRCUnitArr[@Name="추억의 말뚝박기 놀이"]', doc);
|
||||
|
||||
if (crcUnitArrNode) {
|
||||
// CRCUnitArr Name="추억의 말뚝박기 놀이"가 몇 번째 CROwneUnit 요소인지 찾기
|
||||
const unitOrderNode = xpath.select("//CRTransFilter[1]/(@ID|@Range|@ClipIndex)", doc);
|
||||
|
||||
|
||||
console.log('unitOrderNode:', unitOrderNode);
|
||||
|
||||
} else {
|
||||
console.log('CRCUnitArr Name="추억의 말뚝박기 놀이" not found.');
|
||||
}
|
||||
371
제2501회 정기 DIC B형.json
Normal file
371
제2501회 정기 DIC B형.json
Normal file
@@ -0,0 +1,371 @@
|
||||
{
|
||||
"0": {
|
||||
"1": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"2": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"3": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"4": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"5": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"6": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"7": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"8": {
|
||||
"ele": "$[?(@.width == 65 && @.height == 45)]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"1": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"2": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"3": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"4": {
|
||||
"ele": "$.children[?(@.name=='동네쉼터')]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
},
|
||||
"5": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"6": {
|
||||
"ele": "$.children[?(@.name=='Neighborhood Friends')].name",
|
||||
"value": "Neighborhood Friends",
|
||||
"point": 10
|
||||
},
|
||||
"7": {
|
||||
"ele": "$.children[?(@.name=='Neighborhood Friends')].text.font.names[0]",
|
||||
"type": "font",
|
||||
"value": "Arial",
|
||||
"point": 10
|
||||
},
|
||||
"8": {
|
||||
"ele": "$.children[?(@.name=='Neighborhood Friends')].text.font.names[0]",
|
||||
"value": "Arial-BoldItalicMT",
|
||||
"point": 10
|
||||
},
|
||||
"9": {
|
||||
"ele": "$.children[?(@.name=='Neighborhood Friends')].text.font.sizes[0]",
|
||||
"value": 48,
|
||||
"point": 10
|
||||
},
|
||||
"10": {
|
||||
"ele": "$.children[?(@.name=='Neighborhood Friends')].text.font.colors[0]",
|
||||
"type": "color",
|
||||
"value": "ffa200",
|
||||
"point": 10
|
||||
},
|
||||
"11": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"12": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"13": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"14": {
|
||||
"ele": "$.children[?(@.name=='동네 친구들')].name",
|
||||
"value": "동네 친구들",
|
||||
"point": 10
|
||||
},
|
||||
"15": {
|
||||
"ele": "$.children[?(@.name=='동네 친구들')].text.font.names[0]",
|
||||
"type": "font",
|
||||
"value": "GungsuhChe",
|
||||
"point": 10
|
||||
},
|
||||
"16": {
|
||||
"ele": "$.children[?(@.name=='동네 친구들')].text.font.sizes[0]",
|
||||
"value": 36,
|
||||
"point": 10
|
||||
},
|
||||
"17": {
|
||||
"ele": "$.children[?(@.name=='동네 친구들')].text.font.colors[0]",
|
||||
"type": "color",
|
||||
"value": "27d6dc",
|
||||
"point": 10
|
||||
},
|
||||
"18": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"19": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"20": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"21": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"22": {
|
||||
"ele": "$.children[?(@.name=='동네쉼터')]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
},
|
||||
"23": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"24": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"25": {
|
||||
"ele": "none",
|
||||
"point": 0
|
||||
},
|
||||
"26": {
|
||||
"ele": "$[?(@.width == 65 && @.height == 35)]",
|
||||
"type": "boolean",
|
||||
"point": 10
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"1": {
|
||||
"ele": "//CRClipArr/CRClip[position() = //CRTrackList[1]/CRTrackClip/@ClipIndex]/@Path",
|
||||
"type": "array",
|
||||
"value": [
|
||||
"동영상.mp4",
|
||||
"이미지1.jpg",
|
||||
"이미지3.jpg",
|
||||
"이미지2.jpg"
|
||||
],
|
||||
"point": 4
|
||||
},
|
||||
"2": {
|
||||
"ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed",
|
||||
"value": "140",
|
||||
"point": 2
|
||||
},
|
||||
"3": {
|
||||
"ele": "count(//CRClip[@Path='동영상.mp4']/preceding-sibling::*)",
|
||||
"type": "startend",
|
||||
"start": "0",
|
||||
"end": "340",
|
||||
"point": 2
|
||||
},
|
||||
"4": {
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='동영상.mp4']/preceding-sibling::*)]//CRFilter[@ID='52'][@VID100='10'][@VID103='0.80000001']",
|
||||
"point": 3
|
||||
},
|
||||
"5": {
|
||||
"ele": "//GPString[@VID7='추억의 말뚝박기 놀이']/@VID7",
|
||||
"type": "subtitle",
|
||||
"length": 1,
|
||||
"point": 3
|
||||
},
|
||||
"6": {
|
||||
"ele": "//CRCUnitArr[@Name='추억의 말뚝박기 놀이']//GCUnitPool[@Type='1']/GCUnit[@VID102='바탕체']",
|
||||
"point": 2
|
||||
},
|
||||
"7": {
|
||||
"ele": "//CRCUnitArr[@Name='추억의 말뚝박기 놀이']//GCUnitPool[@Type='1']/GCUnit[@VID101='110']",
|
||||
"point": 2
|
||||
},
|
||||
"8": {
|
||||
"ele": "//CRCUnitArr[@Name='추억의 말뚝박기 놀이']//GCUnitPool/GCUnit[@Type='4']/@VID100",
|
||||
"type": "color",
|
||||
"value": "-270661",
|
||||
"point": 2
|
||||
},
|
||||
"9": {
|
||||
"ele": "//CRCUnitArr[@Name='추억의 말뚝박기 놀이']/@VID600 | //CRCUnitArr[@Name='추억의 말뚝박기 놀이']/@VID601",
|
||||
"type": "multi",
|
||||
"value": [
|
||||
0.292,
|
||||
0.929
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"10": {
|
||||
"existEle": "//CRCUnitArr[@Name='추억의 말뚝박기 놀이']",
|
||||
"ele": "sum(//CRTrackList[@Name='텍스트']/CRTrackClip[not(@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='추억의 말뚝박기 놀이']]/preceding::CROwneUnit))]/@Length)",
|
||||
"type": "searchIndex",
|
||||
"value": 160,
|
||||
"point": 2
|
||||
},
|
||||
"11": {
|
||||
"existEle": "//CRCUnitArr[@Name='추억의 말뚝박기 놀이']",
|
||||
"ele": "//CRTrackList[@Name='텍스트']/CRTrackClip[@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='추억의 말뚝박기 놀이']]/preceding::CROwneUnit)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "120",
|
||||
"point": 2
|
||||
},
|
||||
"12": {
|
||||
"existEle": "//CRClip[@Path='동영상.mp4']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='동영상.mp4']/preceding-sibling::*)]/@Mute",
|
||||
"type": "searchIndex",
|
||||
"value": "1",
|
||||
"point": 2
|
||||
},
|
||||
"13": {
|
||||
"existEle": "//CRClip[@Path='이미지1.jpg']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "180",
|
||||
"point": 2
|
||||
},
|
||||
"14": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]//CRFilter/@ID |//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]//CRFilter/@VID100",
|
||||
"value": [
|
||||
"99",
|
||||
"65"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"15": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@ID|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Range|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지1.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Type",
|
||||
"value": [
|
||||
"19",
|
||||
"460:520",
|
||||
"2"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"16": {
|
||||
"existEle": "//CRClip[@Path='이미지3.jpg']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "150",
|
||||
"point": 2
|
||||
},
|
||||
"17": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]//CRFilter/@ID |//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]//CRFilter/@VID101",
|
||||
"value": [
|
||||
"103",
|
||||
"10"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"18": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@ID|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Range|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지3.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Type",
|
||||
"value": [
|
||||
"10",
|
||||
"640:670",
|
||||
"2"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"19": {
|
||||
"existEle": "//CRClip[@Path='이미지2.jpg']",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "150",
|
||||
"point": 2
|
||||
},
|
||||
"20": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]//CRFilter/@ID |//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]//CRFilter/@VID100",
|
||||
"value": [
|
||||
"184",
|
||||
"20"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"21": {
|
||||
"type": "multi",
|
||||
"ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@ID|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Range|//CRTransFilter[@ClipIndex=count(//CRTrackList/CRTrackClip[@ClipIndex=count(//CRClip[@Path='이미지2.jpg']/preceding-sibling::*)]/preceding-sibling::CRTrackClip)]/@Type",
|
||||
"value": [
|
||||
"0",
|
||||
"760:820",
|
||||
"2"
|
||||
],
|
||||
"point": 2
|
||||
},
|
||||
"22": {
|
||||
"ele": "//GPString[@VID7='동네 풍경' or @VID7='(Neighborhood Scene)']/@VID7",
|
||||
"type": "subtitle",
|
||||
"length": 2,
|
||||
"point": 3
|
||||
},
|
||||
"23": {
|
||||
"ele": "//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)']//GCUnitPool[@Type='1']/GCUnit[@VID102='궁서체']",
|
||||
"point": 2
|
||||
},
|
||||
"24": {
|
||||
"ele": "//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)']//GCUnitPool[@Type='1']/GCUnit[@VID101='160']",
|
||||
"point": 2
|
||||
},
|
||||
"25": {
|
||||
"ele": "//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)']//GCUnitPool/GCUnit[@Type='4']/@VID100",
|
||||
"type": "color",
|
||||
"value": "-1589535",
|
||||
"point": 2
|
||||
},
|
||||
"26": {
|
||||
"ele": "//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)']//GCUnitPool/GCUnit[@Type='2'][@VID100='0.2'][@VID101='-8510694']",
|
||||
"point": 2
|
||||
},
|
||||
"27": {
|
||||
"ele": "//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)'][@VID505='18'][@VID507='2']",
|
||||
"point": 3
|
||||
},
|
||||
"28": {
|
||||
"existEle": "//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)']",
|
||||
"ele": "//CRTrackList[@Name='텍스트']/CRTrackClip[@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='추억의 말뚝박기 놀이']]/preceding::CROwneUnit)]/@Pos",
|
||||
"type": "searchIndex",
|
||||
"value": "0",
|
||||
"point": 2
|
||||
},
|
||||
"29": {
|
||||
"existEle": "//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)']",
|
||||
"ele": "//CRTrackList[@Name='텍스트']/CRTrackClip[(@ClipIndex=count(//CROwneUnit[.//CRCUnitArr[@Name='동네 풍경 (Neighborhood Scene)']]/preceding::CROwneUnit))]/@Length",
|
||||
"type": "searchIndex",
|
||||
"value": "120",
|
||||
"point": 2
|
||||
},
|
||||
"30":{
|
||||
"ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']/CRTrackClip[@Pos='0']",
|
||||
"point": 2
|
||||
},
|
||||
"31":{
|
||||
"ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']/CRTrackClip[@Length='810']",
|
||||
"point": 2
|
||||
},
|
||||
"32":{
|
||||
"ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']//CRFilter[@Type='2'][@ID='1'][@VID8='60']",
|
||||
"point": 2
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
BIN
제2501회 정기 DIC B형.xlsx
Normal file
BIN
제2501회 정기 DIC B형.xlsx
Normal file
Binary file not shown.
BIN
제2501회 정기 DIC C형.xlsx
Normal file
BIN
제2501회 정기 DIC C형.xlsx
Normal file
Binary file not shown.
Reference in New Issue
Block a user