diff --git a/00_DPI_2504B_TEST.xlsx b/00_DPI_2504B_TEST.xlsx new file mode 100644 index 0000000..5536d86 Binary files /dev/null and b/00_DPI_2504B_TEST.xlsx differ diff --git a/DIC_2504B.json b/DIC_2504B.json index fa2cdb4..58030f2 100644 --- a/DIC_2504B.json +++ b/DIC_2504B.json @@ -1,748 +1,737 @@ { - "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": "size", - "value": { - "width": 65, - "height": 45 - }, - "point": 4 - }, - "9": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } - }, + "0": { "1": { - "1": { - "ele": "none", - "point": 0 - }, - "2": { - "ele": "none", - "point": 0 - }, - "3": { - "ele": "none", - "point": 0 - }, - "4": { - "ele": "$.children[?(@.name=='꽃잎들')].name", - "value": "꽃잎들", - "point": 4 - }, - "5": { - "ele": "none", - "point": 0 - }, - "6": { - "ele": "$.children[?(@.name=='Flower Rock')].name", - "value": "Flower Rock", - "point": 4 - }, - "7": { - "ele": "$.children[?(@.name=='Flower Rock')].text.font.names[0]", - "type": "font", - "value": "Arial", - "point": 2 - }, - "8": { - "ele": "$.children[?(@.name=='Flower Rock')].text.font.names[0]", - "value": "Arial-BoldItalicMT", - "point": 2 - }, - "9": { - "ele": "$.children[?(@.name=='Flower Rock')].text.font.sizes[0]", - "value": 48, - "point": 2 - }, - "10": { - "ele": "$.children[?(@.name=='Flower Rock')].text.font.colors[0]", - "type": "color", - "value": "d6f592", - "point": 2 - }, - "11": { - "ele": "none", - "point": 0 - }, - "12": { - "ele": "none", - "point": 0 - }, - "13": { - "ele": "none", - "point": 0 - }, - "14": { - "ele": "$.children[?(@.name=='꽃과 바위')].name", - "value": "꽃과 바위", - "point": 4 - }, - "15": { - "ele": "$.children[?(@.name=='꽃과 바위')].text.font.names[0]", - "type": "font", - "value": "GungsuhChe", - "point": 2, - "desc": { - "돋움체": "DotumChe", - "궁서체": "GungsuhChe", - "굴림체": "GulimChe", - "휴먼옛체": "YetR" - } - }, - "16": { - "ele": "$.children[?(@.name=='꽃과 바위')].text.font.sizes[0]", - "value": 36, - "point": 2 - }, - "17": { - "ele": "$.children[?(@.name=='꽃과 바위')].text.font.colors[0]", - "type": "color", - "value": "0d17d5", - "point": 2 - }, - "18": { - "ele": "none", - "point": 0 - }, - "19": { - "ele": "none", - "point": 0 - }, - "20": { - "ele": "none", - "point": 0 - }, - "21": { - "ele": "none", - "point": 0 - }, - "22": { - "ele": "$.children[?(@.name=='노랑꽃')].name", - "value": "노랑꽃", - "point": 4 - }, - "23": { - "ele": "none", - "point": 0 - }, - "24": { - "ele": "none", - "point": 0 - }, - "25": { - "ele": "none", - "point": 0 - }, - "26": { - "ele": "$[?(@.width == 65 && @.height == 35)]", - "type": "size", - "value": { - "width": 65, - "height": 35 - }, - "point": 5 - }, - "27": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 }, "2": { - "1": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[not(@Length<='5' and @ClipLength='-1')]/@ClipIndex", - "type": "mediaOrder", - "value": [ - "동영상.mp4", - "이미지3.jpg", - "이미지1.jpg", - "이미지2.jpg" - ], - "point": 4, - "desc": "비디오1 트랙에 있는 클립의 ClipIndex값을 기준으로 CRClipArr에서 Path값을 가져와서 정답 채점, 클립의 ClipIndex값이 -1인 경우와 길이가 5프레임 이하인 경우는 제외한다." - }, - "2": { - "ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed", - "type": "oneAnswer", - "value": { - "speed": "140" - }, - "point": 2, - "desc": "100당 1배속 / 130 = 1.3배속" - }, - "3": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", - "type": "startEnd", - "media": "동영상.mp4", - "value": { - "start": "0", - "end": "370" - }, - "point": 2, - "desc": "시작시간과 재생시간 정답값 입력, 3번문항은 '동영상.mp4' 클립의 길이를 확인하는 문항이므로 media는 수정할 필요가 없다." - }, - "4": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "effect", - "media": "동영상.mp4", - "value": { - "ID": "44", - "VID100": "8", - "VID103": "0.89999998" - }, - "point": 3, - "desc": "value값의 키값(VID___)은 이펙트의 속성종류에 따라 변경되므로 채점기준표작성시 확인 필요" - }, - "5": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", - "search": "화단의 꽃들", - "type": "video.Text", - "value": "화단의 꽃들", - "point": 3 - }, - "6": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", - "search": "화단의 꽃들", - "type": "video.Text", - "value": "돋움체", - "point": 2 - }, - "7": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", - "search": "화단의 꽃들", - "type": "video.Text", - "value": "110", - "point": 2 - }, - "8": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", - "search": "화단의 꽃들", - "type": "video.Text.Color", - "value": "ff531b", - "point": 2, - "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" - }, - "9": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr/@*[name()='VID600' or name()='VID601']", - "search": "화단의 꽃들", - "type": "video.Location", - "value": [ - "0.38333333", - "0.92962962" - ], - "point": 2, - "desc": "정답 파일의 자막 좌표를 기준으로 프로그램 내부적으로 0.1까지 오차를 허용한다" - }, - "10": { - "ele": "", - "search": "화단의 꽃들", - "type": "video.StartTime", - "value": 170, - "point": 2, - "desc": "내부적으로 자막의 시작시간과 길이를 계산" - }, - "11": { - "ele": "", - "search": "화단의 꽃들", - "type": "video.Length", - "value": 150, - "point": 2, - "desc": "내부적으로 자막의 시작시간과 길이를 계산" - }, - "12": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Mute", - "type": "Mute", - "media": "동영상.mp4", - "value": "1", - "point": 2 - }, - "13": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", - "type": "imageLength", - "media": "이미지3.jpg", - "value": "180", - "point": 2 - }, - "14": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "imageOverlay", - "media": "이미지3.jpg", - "value": { - "ID": "67", - "VID102": "40" - }, - "point": 2 - }, - "15": { - "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", - "type": "clipTransition", - "media": "이미지3.jpg", - "value": { - "ID": "10", - "Range": "490:550", - "Type": "2" - }, - "point": 2, - "desc": "오버랩일 경우 Type속성값 16으로 변경" - }, - "16": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", - "type": "imageLength", - "media": "이미지1.jpg", - "value": "150", - "point": 2 - }, - "17": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "imageOverlay", - "media": "이미지1.jpg", - "value": { - "ID": "184", - "VID102": "30" - }, - "point": 2 - }, - "18": { - "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", - "type": "clipTransition", - "media": "이미지1.jpg", - "value": { - "ID": "19", - "Range": "650:680", - "Type": "2" - }, - "point": 2, - "desc": "오버랩일 경우 Type속성값 16으로 변경" - }, - "19": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", - "type": "imageLength", - "media": "이미지2.jpg", - "value": "180", - "point": 2 - }, - "20": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "imageOverlay", - "media": "이미지2.jpg", - "value": { - "ID": "67", - "VID102": "30" - }, - "point": 2 - }, - "21": { - "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", - "type": "clipTransition", - "media": "이미지2.jpg", - "value": { - "ID": "10", - "Range": "800:860", - "Type": "2" - }, - "point": 2, - "desc": "오버랩일 경우 Type속성값 16으로 변경" - }, - "22": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "video.Text", - "value": "아름다운 꽃 축제 (Happy Flower Festival)", - "point": 3 - }, - "23": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "video.Text", - "value": "궁서체", - "point": 2 - }, - "24": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "video.Text", - "value": "140", - "point": 2 - }, - "25": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "video.Text.Color", - "value": "fd5721", - "point": 2, - "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" - }, - "26": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='2']", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "video.Text.Outline", - "value": { - "width": "30", - "color": "fff9c4" - }, - "point": 2, - "desc": "두께는 XML에서는 소수점으로 표기되지만, 프로그램 내부적으로 변환하여 사용하므로 현재 파일에서는 정수로 작성" - }, - "27": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "opening.Text.FadeInEffect", - "value": { - "ID": "4", - "PlayTime": "2" - }, - "point": 3, - "desc": "오프닝자막의 나타나기 효과를 확인하는 문항. id속성은 VID505, playtime속성은 VID507으로 XML 내부에 표기되어 있다." - }, - "28": { - "ele": "{search}", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "opening.StartTime", - "value": 0, - "point": 2, - "desc": "오프닝자막의 시작시간 value 속성만 수정" - }, - "29": { - "ele": "{search}", - "search": "아름다운 꽃 축제 (Happy Flower Festival)", - "type": "opening.Length", - "value": 120, - "point": 2 - }, - "30": { - "ele": "", - "type": "audio.StartTime", - "media": "음악.mp3", - "value": 0, - "point": 2 - }, - "31": { - "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", - "type": "audio.EndTime", - "media": "음악.mp3", - "value": 810, - "point": 2 - }, - "32": { - "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "audio.Effect", - "media": "음악.mp3", - "value": { - "ID": "1", - "PlayTime": "90" - }, - "point": 2, - "desc": "ID속성-페이드인:0 / 페이드아웃: 1" - }, - "33": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 + }, + "3": { + "ele": "none", + "point": 0 }, "4": { - "1": { - "type": "canvas.Size", - "ele": "//Document/Width/@value | //Document/Height/@value", - "value": [ - "650", - "350" - ], - "point": 5, - "desc": "캔버스 사이즈 650*350" - }, - "2": { - "type": "none", - "ele": "", - "point": 5, - "desc": "자유 변형 문항은 채점 불가" - }, - "3": { - "type": "layer.Exists", - "ele": "//Layer/Name/@value", - "value": "Flower", - "point": 5, - "desc": "Flower 레이어가 있는지 여부 체크" - }, - "4": { - "type": "layer.Effects", - "ele": "//Layer[Name[@value='{search}']]/Effects/Item", - "search": "Flower", - "value": { - "name": "세피아", - "option": { - "U": "75", - "V": "150" - } - }, - "point": 5, - "desc": "Flower 레이어의 효과 체크" - }, - "5": { - "type": "none", - "ele": "", - "point": 6, - "desc": "올가미 도구/이미지 문항은 채점 불가" - }, - "6": { - "type": "exists", - "ele": "//Layer/Effects/Item/Name/@value", - "value": "세피아", - "point": 6, - "desc": "세피아 효과가 있는지 여부 체크" - }, - "7": { - "type": "exists", - "ele": "//Layer/Shapes/Shape/shape_type/@value", - "value": "ELLIPSE", - "point": 3, - "desc": "레이어 쉐이프 타입이 타원인지 체크" - }, - "8": { - "type": "shape.size", - "ele": "//Layer//op_points", - "value": { - "width": 120, - "height": 120 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "9": { - "type": "shape.color", - "ele": "//Layer//Shape[contains(draw_type/@value, 'Interior')]/secondary_color/@value", - "value": "7097BB", - "point": 6, - "desc": "" - }, - "10": { - "type": "layer.blend.opacity", - "ele": "//Layer", - "value": { - "BlendOp": "반사", - "Opacity": "80" - }, - "point": 6 - }, - "11": { - "type": "none", - "ele": "", - "point": 0, - "desc": "기본설정" - }, - "12": { - "type": "none", - "ele": "", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 }, "5": { - "1": { - "type": "canvas.Size", - "ele": "//Document/Width/@value | //Document/Height/@value", - "value": [ - "650", - "450" - ], - "point": 5, - "desc": "캔버스 사이즈 650*450" - }, - "2": { - "type": "none", - "ele": "", - "point": 5, - "desc": "배경색 문항은 채점 불가" - }, - "3": { - "type": "exists", - "ele": "//Layer/MaskOpType/@value", - "value": "Layering", - "point": 6, - "desc": "레이어 마스크 설정 확인" - }, - "4": { - "type": "none", - "ele": "", - "point": 6, - "desc": "가로방향 흐릿하게 문항은 채점 불가" - }, - "5": { - "type": "exists", - "ele": "//Layer//shape_type/@value", - "value": "ROUNDED_RECTANGLE", - "point": 3 - }, - "6": { - "type": "shape.size", - "ele": "//Layer//op_points", - "value": { - "width": 400, - "height": 60 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "7": { - "type": "gradient.color", - "ele": "//Layer/Shapes/Shape", - "startColor": "gradient_start_color/@value", - "endColor": "gradient_end_color/@value", - "value": { - "startColor": "ffe000", - "endColor": "34A159" - }, - "point": 6 - }, - "8": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/lines/Item/@value", - "value": "흰 꽃 사이 노란 꽃", - "point": 5 - }, - "9": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Name/@value", - "value": "맑은 고딕", - "point": 3 - }, - "10": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/{style}/@value", - "style": "Italic", - "value": "True", - "point": 3 - }, - "11": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Size/@value", - "value": "30", - "point": 3 - }, - "12": { - "type": "text.color", - "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Interior')]/secondary_color/@value", - "value": "b46Ef8", - "point": 3 - }, - "13": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/outline_peninfo/Width/@value", - "value": "7", - "point": 3 - }, - "14": { - "type": "text.color", - "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Outline')]/primary_color/@value", - "value": "ffffff", - "point": 3 - }, - "15": { - "type": "exists", - "ele": "//Layer/MaskOpType/@value", - "value": "Clipping", - "point": 6, - "desc": "클리핑 마스크 항목은 별도 레이어로 추가되고 해당 속성을 추가해놓은 레이어가 있는지 여부 체크 함" - }, - "16": { - "type": "exists", - "ele": "//Layer/Shapes/Shape/shape_type/@value", - "value": "RECTANGLE", - "point": 3, - "desc": { - "사각형": "RECTANGLE" - } - }, - "17": { - "type": "clipping.size", - "ele": "//Layer//Shape[shape_type/@value='{option}']//op_points", - "option": "RECTANGLE", - "value": { - "width": 150, - "height": 150 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "18": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='{option}']/outline_peninfo/Width/@value", - "option": "RECTANGLE", - "value": "7", - "point": 3 - }, - "19": { - "type": "clipping.color", - "ele": "//Layer//Shape[shape_type/@value='{option}' and contains(draw_type/@value, 'Outline')]/primary_color/@value", - "option": "RECTANGLE", - "value": "e8e88e", - "point": 3, - "desc": "채우기:secondary_color, 외곽선:primary_color" - }, - "20": { - "type": "shadow", - "ele": "//Layer//Shape[shape_type/@value='{option}']", - "ele2": { - "shadow": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]", - "width": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_width/@value", - "distance": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_distance/@value", - "blur": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_blur/@value", - "angle": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_angle/@value" - }, - "option": "RECTANGLE", - "value": { - "shadow": true, - "width": "3", - "distance": "5", - "blur": "1", - "angle": "320" - }, - "point": 5, - "desc": "그림자 속성이 있는 경우 그림자 속성의 너비, 거리, 흐림 정도, 각도를 비교하여 정답 채점" - }, - "21": { - "type": "none", - "ele": "", - "point": 0, - "desc": "기본설정" - }, - "22": { - "type": "none", - "ele": "", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 + }, + "6": { + "ele": "none", + "point": 0 + }, + "7": { + "ele": "none", + "point": 0 + }, + "8": { + "ele": "$[?(@.width == 65 && @.height == 45)]", + "type": "size", + "value": { + "width": 65, + "height": 45 + }, + "point": 4 + }, + "9": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" } -} \ No newline at end of file + }, + "1": { + "1": { + "ele": "none", + "point": 0 + }, + "2": { + "ele": "none", + "point": 0 + }, + "3": { + "ele": "none", + "point": 0 + }, + "4": { + "ele": "$.children[?(@.name=='꽃잎들')].name", + "value": "꽃잎들", + "point": 4 + }, + "5": { + "ele": "none", + "point": 0 + }, + "6": { + "ele": "$.children[?(@.name=='Flower Rock')].name", + "value": "Flower Rock", + "point": 4 + }, + "7": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.names[0]", + "type": "font", + "value": "Arial", + "point": 2 + }, + "8": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.names[0]", + "value": "Arial-BoldItalicMT", + "point": 2 + }, + "9": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.sizes[0]", + "value": 48, + "point": 2 + }, + "10": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.colors[0]", + "type": "color", + "value": "d6f592", + "point": 2 + }, + "11": { + "ele": "none", + "point": 0 + }, + "12": { + "ele": "none", + "point": 0 + }, + "13": { + "ele": "none", + "point": 0 + }, + "14": { + "ele": "$.children[?(@.name=='꽃과 바위')].name", + "value": "꽃과 바위", + "point": 4 + }, + "15": { + "ele": "$.children[?(@.name=='꽃과 바위')].text.font.names[0]", + "type": "font", + "value": "GungsuhChe", + "point": 2, + "desc": { + "돋움체": "DotumChe", + "궁서체": "GungsuhChe", + "굴림체": "GulimChe", + "휴먼옛체": "YetR" + } + }, + "16": { + "ele": "$.children[?(@.name=='꽃과 바위')].text.font.sizes[0]", + "value": 36, + "point": 2 + }, + "17": { + "ele": "$.children[?(@.name=='꽃과 바위')].text.font.colors[0]", + "type": "color", + "value": "0d17d5", + "point": 2 + }, + "18": { + "ele": "none", + "point": 0 + }, + "19": { + "ele": "none", + "point": 0 + }, + "20": { + "ele": "none", + "point": 0 + }, + "21": { + "ele": "none", + "point": 0 + }, + "22": { + "ele": "$.children[?(@.name=='노랑꽃')].name", + "value": "노랑꽃", + "point": 4 + }, + "23": { + "ele": "none", + "point": 0 + }, + "24": { + "ele": "none", + "point": 0 + }, + "25": { + "ele": "none", + "point": 0 + }, + "26": { + "ele": "$[?(@.width == 65 && @.height == 35)]", + "type": "size", + "value": { + "width": 65, + "height": 35 + }, + "point": 5 + }, + "27": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "2": { + "1": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[not(@Length<='5' and @ClipLength='-1')]/@ClipIndex", + "type": "mediaOrder", + "value": ["동영상.mp4", "이미지3.jpg", "이미지1.jpg", "이미지2.jpg"], + "point": 4, + "desc": "비디오1 트랙에 있는 클립의 ClipIndex값을 기준으로 CRClipArr에서 Path값을 가져와서 정답 채점, 클립의 ClipIndex값이 -1인 경우와 길이가 5프레임 이하인 경우는 제외한다." + }, + "2": { + "ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed", + "type": "oneAnswer", + "value": { + "speed": "140" + }, + "point": 2, + "desc": "100당 1배속 / 130 = 1.3배속" + }, + "3": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", + "type": "startEnd", + "media": "동영상.mp4", + "value": { + "start": "0", + "end": "370" + }, + "point": 2, + "desc": "시작시간과 재생시간 정답값 입력, 3번문항은 '동영상.mp4' 클립의 길이를 확인하는 문항이므로 media는 수정할 필요가 없다." + }, + "4": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "effect", + "media": "동영상.mp4", + "value": { + "ID": "44", + "VID100": "8", + "VID103": "0.89999998" + }, + "point": 3, + "desc": "value값의 키값(VID___)은 이펙트의 속성종류에 따라 변경되므로 채점기준표작성시 확인 필요" + }, + "5": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", + "search": "화단의 꽃들", + "type": "video.Text", + "value": "화단의 꽃들", + "point": 3 + }, + "6": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", + "search": "화단의 꽃들", + "type": "video.Text", + "value": "돋움체", + "point": 2 + }, + "7": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", + "search": "화단의 꽃들", + "type": "video.Text", + "value": "110", + "point": 2 + }, + "8": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", + "search": "화단의 꽃들", + "type": "video.Text.Color", + "value": "ff531b", + "point": 2, + "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" + }, + "9": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr/@*[name()='VID600' or name()='VID601']", + "search": "화단의 꽃들", + "type": "video.Location", + "value": ["0.38333333", "0.92962962"], + "point": 2, + "desc": "정답 파일의 자막 좌표를 기준으로 프로그램 내부적으로 0.1까지 오차를 허용한다" + }, + "10": { + "ele": "", + "search": "화단의 꽃들", + "type": "video.StartTime", + "value": 170, + "point": 2, + "desc": "내부적으로 자막의 시작시간과 길이를 계산" + }, + "11": { + "ele": "", + "search": "화단의 꽃들", + "type": "video.Length", + "value": 150, + "point": 2, + "desc": "내부적으로 자막의 시작시간과 길이를 계산" + }, + "12": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Mute", + "type": "Mute", + "media": "동영상.mp4", + "value": "1", + "point": 2 + }, + "13": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", + "type": "imageLength", + "media": "이미지3.jpg", + "value": "180", + "point": 2 + }, + "14": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "imageOverlay", + "media": "이미지3.jpg", + "value": { + "ID": "67", + "VID102": "40" + }, + "point": 2, + "desc": "오버레이 속성 키값(VID10X) 확인하고 변경" + }, + "15": { + "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", + "type": "clipTransition", + "media": "이미지3.jpg", + "value": { + "ID": "10", + "Range": "490:550", + "Type": "2" + }, + "point": 2, + "desc": "오버랩일 경우 Type속성값 16으로 변경" + }, + "16": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", + "type": "imageLength", + "media": "이미지1.jpg", + "value": "180", + "point": 2 + }, + "17": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "imageOverlay", + "media": "이미지1.jpg", + "value": { + "ID": "103", + "VID102": "7" + }, + "point": 2, + "desc": "오버레이 속성 키값(VID10X) 확인하고 변경" + }, + "18": { + "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", + "type": "clipTransition", + "media": "이미지1.jpg", + "value": { + "ID": "12", + "Range": "670:730", + "Type": "2" + }, + "point": 2, + "desc": "오버랩일 경우 Type속성값 16으로 변경" + }, + "19": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", + "type": "imageLength", + "media": "이미지2.jpg", + "value": "150", + "point": 2 + }, + "20": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "imageOverlay", + "media": "이미지2.jpg", + "value": { + "ID": "102", + "VID101": "3" + }, + "point": 2, + "desc": "오버레이 속성 키값(VID10X) 확인하고 변경" + }, + "21": { + "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", + "type": "clipTransition", + "media": "이미지2.jpg", + "value": { + "ID": "0", + "Range": "850:880", + "Type": "2" + }, + "point": 2, + "desc": "오버랩일 경우 Type속성값 16으로 변경" + }, + "22": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text", + "value": "아름다운 꽃 축제 (Happy Flower Festival)", + "point": 3 + }, + "23": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text", + "value": "궁서체", + "point": 2 + }, + "24": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text", + "value": "140", + "point": 2 + }, + "25": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text.Color", + "value": "ec008c", + "point": 2, + "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" + }, + "26": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='2']", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text.Outline", + "value": { + "width": "40", + "color": "fff9c4" + }, + "point": 2, + "desc": "두께는 XML에서는 소수점으로 표기되지만, 프로그램 내부적으로 변환하여 사용하므로 현재 파일에서는 정수로 작성" + }, + "27": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "opening.Text.FadeInEffect", + "value": { + "ID": "14", + "PlayTime": "2" + }, + "point": 3, + "desc": "오프닝자막의 나타나기 효과를 확인하는 문항. id속성은 VID505, playtime속성은 VID507으로 XML 내부에 표기되어 있다." + }, + "28": { + "ele": "", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "opening.StartTime", + "value": 0, + "point": 2, + "desc": "오프닝자막의 시작시간 value 속성만 수정" + }, + "29": { + "ele": "", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "opening.Length", + "value": 120, + "point": 2 + }, + "30": { + "ele": "", + "type": "audio.StartTime", + "media": "음악.mp3", + "value": 0, + "point": 2 + }, + "31": { + "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", + "type": "audio.EndTime", + "media": "음악.mp3", + "value": "870", + "point": 2 + }, + "32": { + "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "audio.Effect", + "media": "음악.mp3", + "value": { + "ID": "1", + "PlayTime": "60" + }, + "point": 2, + "desc": "ID속성-페이드인:0 / 페이드아웃: 1" + }, + "33": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "4": { + "1": { + "type": "canvas.Size", + "ele": "//Document/Width/@value | //Document/Height/@value", + "value": ["650", "350"], + "point": 5, + "desc": "캔버스 사이즈 650*350" + }, + "2": { + "type": "none", + "ele": "", + "point": 5, + "desc": "자유 변형 문항은 채점 불가" + }, + "3": { + "type": "layer.exists", + "ele": "//Layer/Name/@value", + "value": "Flower", + "point": 5, + "desc": "Flower 레이어가 있는지 여부 체크" + }, + "4": { + "type": "layer.Effects", + "ele": "//Layer[Name[@value='{search}']]/Effects/Item", + "search": "Flower", + "value": { + "name": "생동감", + "option": { + "생동감": "40" + } + }, + "point": 5, + "desc": { + "흑백": "강도", + "밝기/대비": ["밝기", "대비"], + "노출": "노출", + "색조/채도": ["색조", "채도", "명도"], + "감마":["리프트","감마","게인"], + "세피아":["U","V"], + "생동감": "생동감" + } + }, + "5": { + "type": "none", + "ele": "", + "point": 6, + "desc": "올가미 도구/이미지 문항은 채점 불가" + }, + "6": { + "type": "exists", + "ele": "//Layer/Effects/Item/Name/@value", + "value": "세피아", + "point": 6, + "desc": "세피아 효과가 있는지 여부 체크" + }, + "7": { + "type": "exists", + "ele": "//Layer/Shapes/Shape/shape_type/@value", + "value": "ELLIPSE", + "point": 3, + "desc": "레이어 쉐이프 타입이 타원인지 체크" + }, + "8": { + "type": "shape.size", + "ele": "//Layer//op_points", + "value": { + "width": 120, + "height": 120 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "9": { + "type": "shape.color", + "ele": "//Layer//Shape[contains(draw_type/@value, 'Interior')]/secondary_color/@value", + "value": "7097BB", + "point": 6, + "desc": "" + }, + "10": { + "type": "layer.blend.opacity", + "ele": "//Layer", + "value": { + "BlendOp": "반사", + "Opacity": "80" + }, + "point": 6 + }, + "11": { + "type": "none", + "ele": "", + "point": 0, + "desc": "기본설정" + }, + "12": { + "type": "none", + "ele": "", + "point": 0, + "desc": "파일명 확인" + } + }, + "5": { + "1": { + "type": "canvas.Size", + "ele": "//Document/Width/@value | //Document/Height/@value", + "value": ["650", "450"], + "point": 5, + "desc": "캔버스 사이즈 650*450" + }, + "2": { + "type": "none", + "ele": "", + "point": 5, + "desc": "배경색 문항은 채점 불가" + }, + "3": { + "type": "exists", + "ele": "//Layer/MaskOpType/@value", + "value": "Layering", + "point": 6, + "desc": "레이어 마스크 설정 확인" + }, + "4": { + "type": "none", + "ele": "", + "point": 6, + "desc": "가로방향 흐릿하게 문항은 채점 불가" + }, + "5": { + "type": "exists", + "ele": "//Layer//shape_type/@value", + "value": "ROUNDED_RECTANGLE", + "point": 3 + }, + "6": { + "type": "shape.size", + "ele": "//Layer//op_points", + "value": { + "width": 400, + "height": 60 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "7": { + "type": "gradient.color", + "ele": "//Layer/Shapes/Shape", + "startColor": "gradient_start_color/@value", + "endColor": "gradient_end_color/@value", + "value": { + "startColor": "ffe000", + "endColor": "34A159" + }, + "point": 6 + }, + "8": { + "type": "text.exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/lines/Item/@value", + "value": "흰 꽃 사이 노란 꽃", + "point": 5 + }, + "9": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Name/@value", + "value": "맑은 고딕", + "point": 3 + }, + "10": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/{style}/@value", + "style": "Italic", + "value": "True", + "point": 3 + }, + "11": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Size/@value", + "value": "30", + "point": 3 + }, + "12": { + "type": "text.color", + "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Interior')]/secondary_color/@value", + "value": "b46Ef8", + "point": 3 + }, + "13": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/outline_peninfo/Width/@value", + "value": "7", + "point": 3 + }, + "14": { + "type": "text.color", + "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Outline')]/primary_color/@value", + "value": "ffffff", + "point": 3 + }, + "15": { + "type": "exists", + "ele": "//Layer/MaskOpType/@value", + "value": "Clipping", + "point": 6, + "desc": "클리핑 마스크 항목은 별도 레이어로 추가되고 해당 속성을 추가해놓은 레이어가 있는지 여부 체크 함" + }, + "16": { + "type": "exists", + "ele": "//Layer/Shapes/Shape/shape_type/@value", + "value": "RECTANGLE", + "point": 3, + "desc": { + "사각형": "RECTANGLE" + } + }, + "17": { + "type": "clipping.size", + "ele": "//Layer//Shape[shape_type/@value='{option}']//op_points", + "option": "RECTANGLE", + "value": { + "width": 150, + "height": 150 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "18": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='{option}']/outline_peninfo/Width/@value", + "option": "RECTANGLE", + "value": "7", + "point": 3 + }, + "19": { + "type": "clipping.color", + "ele": "//Layer//Shape[shape_type/@value='{option}' and contains(draw_type/@value, 'Outline')]/primary_color/@value", + "option": "RECTANGLE", + "value": "e8e88e", + "point": 3, + "desc": "채우기:secondary_color, 외곽선:primary_color" + }, + "20": { + "type": "shadow", + "ele": "//Layer//Shape[shape_type/@value='{option}']", + "option": "RECTANGLE", + "value": { + "shadow": true, + "width": "3", + "distance": "5", + "blur": "1", + "angle": "320" + }, + "point": 5, + "desc": "그림자 속성이 있는 경우 그림자 속성의 너비, 거리, 흐림 정도, 각도를 비교하여 정답 채점" + }, + "21": { + "type": "none", + "ele": "", + "point": 0, + "desc": "기본설정" + }, + "22": { + "type": "none", + "ele": "", + "point": 0, + "desc": "파일명 확인" + } + } +} diff --git a/DIC_2505A.json b/DIC_2505A.json index 6dfc21a..5942aec 100644 --- a/DIC_2505A.json +++ b/DIC_2505A.json @@ -1,728 +1,681 @@ { - "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": "size", - "value": { - "width": 65, - "height": 45 - }, - "point": 4 - }, - "9": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } - }, + "0": { "1": { - "1": { - "ele": "none", - "point": 0 - }, - "2": { - "ele": "none", - "point": 0 - }, - "3": { - "ele": "none", - "point": 0 - }, - "4": { - "ele": "$.children[?(@.name=='놀이터')].name", - "value": "놀이터", - "point": 4 - }, - "5": { - "ele": "none", - "point": 0 - }, - "6": { - "ele": "$.children[?(@.name=='Forest Playground')].name", - "value": "Forest Playground", - "point": 4 - }, - "7": { - "ele": "$.children[?(@.name=='Forest Playground')].text.font.names[0]", - "type": "font", - "value": "Arial", - "point": 2 - }, - "8": { - "ele": "$.children[?(@.name=='Forest Playground')].text.font.names[0]", - "value": "Arial-BoldItalicMT", - "point": 2 - }, - "9": { - "ele": "$.children[?(@.name=='Forest Playground')].text.font.sizes[0]", - "value": 48, - "point": 2 - }, - "10": { - "ele": "$.children[?(@.name=='Forest Playground')].text.font.colors[0]", - "type": "color", - "value": "0096ff", - "point": 2 - }, - "11": { - "ele": "none", - "point": 0 - }, - "12": { - "ele": "none", - "point": 0 - }, - "13": { - "ele": "none", - "point": 0 - }, - "14": { - "ele": "$.children[?(@.name=='숲속 놀이터')].name", - "value": "숲속 놀이터", - "point": 4 - }, - "15": { - "ele": "$.children[?(@.name=='숲속 놀이터')].text.font.names[0]", - "type": "font", - "value": "GulimChe", - "point": 2, - "desc": { - "돋움체":"DotumChe", - "궁서체":"GungsuhChe", - "굴림체":"GulimChe", - "옛":"YetR" - } - }, - "16": { - "ele": "$.children[?(@.name=='숲속 놀이터')].text.font.sizes[0]", - "value": 36, - "point": 2 - }, - "17": { - "ele": "$.children[?(@.name=='숲속 놀이터')].text.font.colors[0]", - "type": "color", - "value": "0c3f00", - "point": 2 - }, - "18": { - "ele": "none", - "point": 0 - }, - "19": { - "ele": "none", - "point": 0 - }, - "20": { - "ele": "none", - "point": 0 - }, - "21": { - "ele": "none", - "point": 0 - }, - "22": { - "ele": "$.children[?(@.name=='바람개비')].name", - "value": "바람개비", - "point": 4 - }, - "23": { - "ele": "none", - "point": 0 - }, - "24": { - "ele": "none", - "point": 0 - }, - "25": { - "ele": "none", - "point": 0 - }, - "26": { - "ele": "$[?(@.width == 65 && @.height == 35)]", - "type": "size", - "value": { - "width": 65, - "height": 35 - }, - "point": 5 - }, - "27": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 }, "2": { - "desc": "videoStartTime 항목은 동영상파일>자막>시작시간 문항의 정답을 작성", - "videoStartTime": 170, - "openingStartTime": 0, - "1": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[not(@Length<='5' and @ClipLength='-1')]/@ClipIndex", - "type": "mediaOrder", - "value": [ - "동영상.mp4", - "이미지3.jpg", - "이미지1.jpg", - "이미지2.jpg" - ], - "point": 4, - "desc": "비디오1 트랙에 있는 클립의 ClipIndex값을 기준으로 CRClipArr에서 Path값을 가져와서 정답 채점, 클립의 ClipIndex값이 -1인 경우와 길이가 5프레임 이하인 경우는 제외한다." - }, - "2": { - "ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed", - "type": "oneAnswer", - "value": { - "speed": "130" - }, - "point": 2, - "desc": "100당 1배속 / 130 = 1.3배속" - }, - "3": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{videoClipIndex}']", - "type": "startEnd", - "media": "동영상.mp4", - "value": { - "start": "0", - "end": "360" - }, - "point": 2, - "desc": "시작시간과 재생시간 정답값 입력, 3번문항은 '동영상.mp4' 클립의 길이를 확인하는 문항이므로 media는 수정할 필요가 없다." - }, - "4": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{videoClipIndex}']//CRFilter", - "type": "effect", - "media": "동영상.mp4", - "value": { - "ID": "168", - "VID102": "10", - "VID100": "0.80000001" - }, - "point": 3, - "desc": "value값의 키값(VID___)은 이펙트의 속성종류에 따라 변경되므로 채점기준표작성시 확인 필요" - }, - "5": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", - "ele2": "//CRCUnitArr[@Name='{search}']/@Name", - "ele3": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@Name", - "type": "video", - "value": "모래 촉감 놀이", - "search": "모래 촉감 놀이", - "point": 3 - }, - "6": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", - "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID102", - "search": "모래 촉감 놀이", - "type": "video", - "value": "굴림체", - "point": 2 - }, - "7": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", - "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID101", - "search": "모래 촉감 놀이", - "type": "video", - "value": "110", - "point": 2 - }, - "8": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", - "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool/GCUnit[@Type='4']/@VID100", - "search": "모래 촉감 놀이", - "type": "video", - "value": "-13778690", - "point": 2 - }, - "9": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@*[name()='VID600' or name()='VID601']", - "ele2": "//CRCUnitArr[@Name='{search}']/@*[name()='VID600' or name()='VID601']", - "type": "video", - "search": "모래 촉감 놀이", - "value": [ - 0.35312501, - 0.92962962 - ], - "point": 2 - }, - "10": { - "ele": "{search}", - "search": "모래 촉감 놀이", - "type": "videoStartTime", - "value": 170, - "point": 2 - }, - "11": { - "ele": "{search}", - "search": "모래 촉감 놀이", - "type": "videoLength", - "value": 150, - "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='{image}'] | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']", - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/@Length", - "image": "이미지3.jpg", - "type": "searchIndex", - "value": "180", - "point": 2 - }, - "14": { - "type": "multi", - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]//CRFilter/@*[name()='ID' or name()='VID101']", - "image": "이미지3.jpg", - "value": [ - "184", - "5" - ], - "point": 2 - }, - "15": { - "type": "multi", - "ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/preceding-sibling::CRTrackClip)][@Type='2']/@*[name()='ID' or name()='Range' or name()='Type']", - "image": "이미지3.jpg", - "value": [ - "21", - "480:540", - "2" - ], - "point": 2, - "desc": "오버랩일 경우 XPATH구문에서 Type속성값 16으로 변경, 그리고 ClipIndex값은 트랜지션이 끝나는 지점 이미지의 ClipIndex값을 가지게 되어 다음 순서의 이미지로 변경해주어야한다." - }, - "16": { - "existEle": "//CRClip[@Path='{image}'] | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']", - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/@Length", - "image": "이미지1.jpg", - "type": "searchIndex", - "value": "180", - "point": 2 - }, - "17": { - "type": "multi", - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]//CRFilter/@*[name()='ID' or name()='VID100']", - "image": "이미지1.jpg", - "value": [ - "102", - "6" - ], - "point": 2 - }, - "18": { - "type": "multi", - "ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/preceding-sibling::CRTrackClip)][@Type='2']/@*[name()='ID' or name()='Range' or name()='Type']", - "image": "이미지1.jpg", - "value": [ - "9", - "690:720", - "2" - ], - "point": 2, - "desc": "오버랩일 경우 XPATH구문에서 Type속성값 16으로 변경, 그리고 ClipIndex값은 트랜지션이 끝나는 지점 이미지의 ClipIndex값을 가지게 되어 다음 순서의 이미지로 변경해주어야한다." - }, - "19": { - "existEle": "//CRClip[@Path='{image}'] | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']", - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/@Length", - "image": "이미지2.jpg", - "type": "searchIndex", - "value": "150", - "point": 2 - }, - "20": { - "type": "multi", - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]//CRFilter/@*[name()='ID' or name()='VID103']", - "image": "이미지2.jpg", - "value": [ - "67", - "7" - ], - "point": 2 - }, - "21": { - "type": "multi", - "ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/preceding-sibling::CRTrackClip)][@Type='2']/@*[name()='ID' or name()='Range' or name()='Type']", - "image": "이미지2.jpg", - "value": [ - "94", - "840:870", - "2" - ], - "point": 2, - "desc": "오버랩일 경우 XPATH구문에서 Type속성값 16으로 변경, 그리고 ClipIndex값은 트랜지션이 끝나는 지점 이미지의 ClipIndex값을 가지게 되어 다음 순서의 이미지로 변경해주어야한다." - }, - "22": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@Name", - "ele2": "//CRCUnitArr[@Name='{search}']/@Name", - "type": "opening", - "search": "자연 놀이터 (Nature Playground)", - "value": "자연 놀이터 (Nature Playground)", - "point": 3 - }, - "23": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", - "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID102", - "search": "자연 놀이터 (Nature Playground)", - "type": "opening", - "value": "바탕체", - "point": 2 - }, - "24": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", - "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID101", - "search": "자연 놀이터 (Nature Playground)", - "type": "opening", - "value": "140", - "point": 2 - }, - "25": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", - "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool/GCUnit[@Type='4']/@VID100", - "search": "자연 놀이터 (Nature Playground)", - "type": "opening", - "value": "-12808648", - "point": 2 - }, - "26": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='2']/@*[name()='VID100' or name()='VID101']", - "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool/GCUnit[@Type='2']/@*[name()='VID100' or name()='VID101']", - "search": "자연 놀이터 (Nature Playground)", - "type": "opening", - "value": [ - "0.30000001", - "-13107457" - ], - "point": 2 - }, - "27": { - "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@*[name()='VID505' or name()='VID507']", - "ele2": "//CRCUnitArr[@Name='{search}']/@*[name()='VID505' or name()='VID507']", - "search": "자연 놀이터 (Nature Playground)", - "type": "opening", - "value": [ - "14", - "2" - ], - "point": 3 - }, - "28": { - "ele": "sum(//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][{subtitleOrder}]/preceding-sibling::CRTrackClip/@Length)", - "ele2": "sum(//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][@ClipIndex={textClipIndex}]/preceding-sibling::CRTrackClip/@Length)", - "search": "자연 놀이터 (Nature Playground)", - "type": "opening", - "value": 0, - "point": 2 - }, - "29": { - "ele": "//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][{subtitleOrder}]/@Length", - "ele2": "//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][@ClipIndex={textClipIndex}]/@Length", - "search": "자연 놀이터 (Nature Playground)", - "type": "opening", - "value": "120", - "point": 2 - }, - "30": { - "ele": "//CRTrackList[@Name='오디오1'][@Count>='1']/CRTrackClip[1][not(@ClipIndex='-1')]", - "point": 2 - }, - "31": { - "ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']/CRTrackClip[@Length='840']", - "point": 2 - }, - "32": { - "ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']//CRFilter[@Type='2'][@ID='1'][@VID8='60']", - "point": 2 - }, - "33": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 + }, + "3": { + "ele": "none", + "point": 0 }, "4": { - "1": { - "type": "multi", - "ele": "//Document/Width/@value | //Document/Height/@value", - "value": [ - "650", - "350" - ], - "point": 5, - "desc": "캔버스 사이즈 650*350" - }, - "2": { - "ele": "none", - "point": 5, - "desc": "자유 변형 문항은 채점 불가" - }, - "3": { - "type": "isExist", - "ele": "//Layer/Name/@value", - "value": "Flower", - "point": 5, - "desc": "Flower 레이어가 있는지 여부 체크" - }, - "4": { - "type": "multiValue", - "ele": "//Layer[Name[@value='{layer}']]/Effects/Item[EffectData/{option}]/Name/@value | //Layer[Name[@value='{layer}']]/Effects/Item/EffectData/{option}/@value", - "layer": "Flower", - "option": "VibranceValue", - "value": [ - "39", - "생동감" - ], - "point": 5, - "desc": "Flower 레이어의 효과 체크" - }, - "5": { - "ele": "none", - "point": 6, - "desc": "올가미 도구/이미지 문항은 채점 불가" - }, - "6": { - "type": "exists", - "ele": "//Layer/Effects/Item/Name/@value", - "value": "세피아", - "point": 6, - "desc": "세피아 효과가 있는지 여부 체크" - }, - "7": { - "type": "exact", - "ele": "//Layer/Shapes/Shape/shape_type/@value", - "value": "ELLIPSE", - "point": 3, - "desc": "레이어 쉐이프 타입이 타원인지 체크" - }, - "8": { - "type": "size", - "ele": "//Layer//op_points", - "value": { - "width": 120, - "height": 120 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "9": { - "type": "color", - "ele": "//Layer//Shape[contains(draw_type/@value, 'Interior')]/secondary_color/@value", - "value": "7097bb", - "point": 6, - "desc": "색상 코드 비교 시 소문자로 입력할 것" - }, - "10": { - "type": "multiValue", - "ele": "//Layer/BlendOp/@value | //Layer/Opacity/@value", - "value": [ - "반사", - "80" - ], - "point": 6, - "desc": "혼합모드(색 회피율, 불투명도 : 80)" - }, - "11": { - "ele": "none", - "point": 0, - "desc": "기본설정" - }, - "12": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 }, "5": { - "1": { - "type": "multi", - "ele": "//Document/Width/@value | //Document/Height/@value", - "value": [ - "650", - "450" - ], - "point": 5, - "desc": "캔버스 사이즈 650*450" - }, - "2": { - "ele": "none", - "point": 5, - "desc": "배경색 문항은 채점 불가" - }, - "3": { - "type": "exists", - "ele": "//Layer/MaskOpType/@value", - "value": "Layering", - "point": 6 - }, - "4": { - "ele": "none", - "point": 6, - "desc": "가로방향 흐릿하게 문항은 채점 불가" - }, - "5": { - "type": "exists", - "ele": "//Layer//shape_type/@value", - "value": "ROUNDED_RECTANGLE", - "point": 3 - }, - "6": { - "type": "size", - "ele": "//Layer//op_points", - "value": { - "width": 400, - "height": 60 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "7": { - "type": "gradient", - "ele": "//Layer/Shapes/Shape", - "startColor": "gradient_start_color/@value", - "endColor": "gradient_end_color/@value", - "value": { - "startColor": "ffe000", - "endColor": "34a159" - }, - "point": 6 - }, - "8": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/lines/Item/@value", - "value": "흰 꽃 사이 노란 꽃", - "point": 5 - }, - "9": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Name/@value", - "value": "맑은 고딕", - "point": 3 - }, - "10": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/{style}/@value", - "style": "Italic", - "value": "True", - "point": 3 - }, - "11": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Size/@value", - "value": "30", - "point": 3 - }, - "12": { - "type": "color", - "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Interior')]/secondary_color/@value", - "value": "b46ef8", - "point": 3, - "desc": "색상 코드 비교 시 소문자로 입력할 것" - }, - "13": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/outline_peninfo/Width/@value", - "value": "7", - "point": 3 - }, - "14": { - "type": "color", - "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Outline')]/primary_color/@value", - "value": "ffffff", - "point": 3, - "desc": "색상 코드 비교 시 소문자로 입력할 것" - }, - "15": { - "ele": "//Layer[MaskOpType/@value='Clipping'][last()]", - "point": 6, - "desc": "클리핑 마스크 항목은 별도 레이어로 추가되고 해당 속성을 추가해놓은 레이어가 있는지 여부 체크 함" - }, - "16": { - "type": "exists", - "ele": "//Layer/Shapes/Shape/shape_type/@value", - "value": "RECTANGLE", - "point": 3 - }, - "17": { - "type": "size", - "ele": "//Layer//op_points", - "value": { - "width": 150, - "height": 150 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "18": { - "type": "exists", - "ele": "//Layer//outline_peninfo/Width/@value", - "value": "7", - "point": 3 - }, - "19": { - "type": "color", - "ele": "//Layer//Shape[contains(draw_type/@value, 'Outline')]/primary_color/@value", - "value": "e8e88e", - "point": 3, - "desc": "색상 코드 비교 시 소문자로 입력할 것(채우기:secondary_color, 외곽선:primary_color)" - }, - "20": { - "type": "shadow", - "ele": { - "shadow": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]", - "width": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_width/@value", - "distance": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_distance/@value", - "blur": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_blur/@value", - "angle": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_angle/@value" - }, - "value": { - "width": "3", - "distance": "5", - "blur": "1", - "angle": "320" - }, - "point": 5, - "desc": "그림자 속성이 있는 경우 그림자 속성의 너비, 거리, 흐림 정도, 각도를 비교하여 정답 채점" - }, - "21": { - "ele": "none", - "point": 0, - "desc": "기본설정" - }, - "22": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } + "ele": "none", + "point": 0 + }, + "6": { + "ele": "none", + "point": 0 + }, + "7": { + "ele": "none", + "point": 0 + }, + "8": { + "ele": "$[?(@.width == 65 && @.height == 45)]", + "type": "size", + "value": { + "width": 65, + "height": 45 + }, + "point": 4 + }, + "9": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" } -} \ No newline at end of file + }, + "1": { + "1": { + "ele": "none", + "point": 0 + }, + "2": { + "ele": "none", + "point": 0 + }, + "3": { + "ele": "none", + "point": 0 + }, + "4": { + "ele": "$.children[?(@.name=='놀이터')].name", + "value": "놀이터", + "point": 4 + }, + "5": { + "ele": "none", + "point": 0 + }, + "6": { + "ele": "$.children[?(@.name=='Forest Playground')].name", + "value": "Forest Playground", + "point": 4 + }, + "7": { + "ele": "$.children[?(@.name=='Forest Playground')].text.font.names[0]", + "type": "font", + "value": "Arial", + "point": 2 + }, + "8": { + "ele": "$.children[?(@.name=='Forest Playground')].text.font.names[0]", + "value": "Arial-BoldItalicMT", + "point": 2 + }, + "9": { + "ele": "$.children[?(@.name=='Forest Playground')].text.font.sizes[0]", + "value": 48, + "point": 2 + }, + "10": { + "ele": "$.children[?(@.name=='Forest Playground')].text.font.colors[0]", + "type": "color", + "value": "0096ff", + "point": 2 + }, + "11": { + "ele": "none", + "point": 0 + }, + "12": { + "ele": "none", + "point": 0 + }, + "13": { + "ele": "none", + "point": 0 + }, + "14": { + "ele": "$.children[?(@.name=='숲속 놀이터')].name", + "value": "숲속 놀이터", + "point": 4 + }, + "15": { + "ele": "$.children[?(@.name=='숲속 놀이터')].text.font.names[0]", + "type": "font", + "value": "GulimChe", + "point": 2, + "desc": { + "돋움체": "DotumChe", + "궁서체": "GungsuhChe", + "굴림체": "GulimChe", + "옛": "YetR" + } + }, + "16": { + "ele": "$.children[?(@.name=='숲속 놀이터')].text.font.sizes[0]", + "value": 36, + "point": 2 + }, + "17": { + "ele": "$.children[?(@.name=='숲속 놀이터')].text.font.colors[0]", + "type": "color", + "value": "0c3f00", + "point": 2 + }, + "18": { + "ele": "none", + "point": 0 + }, + "19": { + "ele": "none", + "point": 0 + }, + "20": { + "ele": "none", + "point": 0 + }, + "21": { + "ele": "none", + "point": 0 + }, + "22": { + "ele": "$.children[?(@.name=='바람개비')].name", + "value": "바람개비", + "point": 4 + }, + "23": { + "ele": "none", + "point": 0 + }, + "24": { + "ele": "none", + "point": 0 + }, + "25": { + "ele": "none", + "point": 0 + }, + "26": { + "ele": "$[?(@.width == 65 && @.height == 35)]", + "type": "size", + "value": { + "width": 65, + "height": 35 + }, + "point": 5 + }, + "27": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "2": { + "desc": "videoStartTime 항목은 동영상파일>자막>시작시간 문항의 정답을 작성", + "videoStartTime": 170, + "openingStartTime": 0, + "1": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[not(@Length<='5' and @ClipLength='-1')]/@ClipIndex", + "type": "mediaOrder", + "value": ["동영상.mp4", "이미지3.jpg", "이미지1.jpg", "이미지2.jpg"], + "point": 4, + "desc": "비디오1 트랙에 있는 클립의 ClipIndex값을 기준으로 CRClipArr에서 Path값을 가져와서 정답 채점, 클립의 ClipIndex값이 -1인 경우와 길이가 5프레임 이하인 경우는 제외한다." + }, + "2": { + "ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed", + "type": "oneAnswer", + "value": { + "speed": "130" + }, + "point": 2, + "desc": "100당 1배속 / 130 = 1.3배속" + }, + "3": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{videoClipIndex}']", + "type": "startEnd", + "media": "동영상.mp4", + "value": { + "start": "0", + "end": "360" + }, + "point": 2, + "desc": "시작시간과 재생시간 정답값 입력, 3번문항은 '동영상.mp4' 클립의 길이를 확인하는 문항이므로 media는 수정할 필요가 없다." + }, + "4": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{videoClipIndex}']//CRFilter", + "type": "effect", + "media": "동영상.mp4", + "value": { + "ID": "168", + "VID102": "10", + "VID100": "0.80000001" + }, + "point": 3, + "desc": "value값의 키값(VID___)은 이펙트의 속성종류에 따라 변경되므로 채점기준표작성시 확인 필요" + }, + "5": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", + "ele2": "//CRCUnitArr[@Name='{search}']/@Name", + "ele3": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@Name", + "type": "video", + "value": "모래 촉감 놀이", + "search": "모래 촉감 놀이", + "point": 3 + }, + "6": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", + "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID102", + "search": "모래 촉감 놀이", + "type": "video", + "value": "굴림체", + "point": 2 + }, + "7": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", + "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID101", + "search": "모래 촉감 놀이", + "type": "video", + "value": "110", + "point": 2 + }, + "8": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", + "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool/GCUnit[@Type='4']/@VID100", + "search": "모래 촉감 놀이", + "type": "video", + "value": "-13778690", + "point": 2 + }, + "9": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@*[name()='VID600' or name()='VID601']", + "ele2": "//CRCUnitArr[@Name='{search}']/@*[name()='VID600' or name()='VID601']", + "type": "video", + "search": "모래 촉감 놀이", + "value": [0.35312501, 0.92962962], + "point": 2 + }, + "10": { + "ele": "{search}", + "search": "모래 촉감 놀이", + "type": "videoStartTime", + "value": 170, + "point": 2 + }, + "11": { + "ele": "{search}", + "search": "모래 촉감 놀이", + "type": "videoLength", + "value": 150, + "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='{image}'] | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']", + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/@Length", + "image": "이미지3.jpg", + "type": "searchIndex", + "value": "180", + "point": 2 + }, + "14": { + "type": "multi", + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]//CRFilter/@*[name()='ID' or name()='VID101']", + "image": "이미지3.jpg", + "value": ["184", "5"], + "point": 2 + }, + "15": { + "type": "multi", + "ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/preceding-sibling::CRTrackClip)][@Type='2']/@*[name()='ID' or name()='Range' or name()='Type']", + "image": "이미지3.jpg", + "value": ["21", "480:540", "2"], + "point": 2, + "desc": "오버랩일 경우 XPATH구문에서 Type속성값 16으로 변경, 그리고 ClipIndex값은 트랜지션이 끝나는 지점 이미지의 ClipIndex값을 가지게 되어 다음 순서의 이미지로 변경해주어야한다." + }, + "16": { + "existEle": "//CRClip[@Path='{image}'] | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']", + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/@Length", + "image": "이미지1.jpg", + "type": "searchIndex", + "value": "180", + "point": 2 + }, + "17": { + "type": "multi", + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]//CRFilter/@*[name()='ID' or name()='VID100']", + "image": "이미지1.jpg", + "value": ["102", "6"], + "point": 2 + }, + "18": { + "type": "multi", + "ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/preceding-sibling::CRTrackClip)][@Type='2']/@*[name()='ID' or name()='Range' or name()='Type']", + "image": "이미지1.jpg", + "value": ["9", "690:720", "2"], + "point": 2, + "desc": "오버랩일 경우 XPATH구문에서 Type속성값 16으로 변경, 그리고 ClipIndex값은 트랜지션이 끝나는 지점 이미지의 ClipIndex값을 가지게 되어 다음 순서의 이미지로 변경해주어야한다." + }, + "19": { + "existEle": "//CRClip[@Path='{image}'] | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']", + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/@Length", + "image": "이미지2.jpg", + "type": "searchIndex", + "value": "150", + "point": 2 + }, + "20": { + "type": "multi", + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]//CRFilter/@*[name()='ID' or name()='VID103']", + "image": "이미지2.jpg", + "value": ["67", "7"], + "point": 2 + }, + "21": { + "type": "multi", + "ele": "//CRTransFilter[@ClipIndex=count(//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex=count(//CRClip[@Path='{image}']/preceding-sibling::CRClip | //CRClip[@Type='11']/CRCUnitArr[@Path='{image}']/../preceding-sibling::CRClip)][1]/preceding-sibling::CRTrackClip)][@Type='2']/@*[name()='ID' or name()='Range' or name()='Type']", + "image": "이미지2.jpg", + "value": ["94", "840:870", "2"], + "point": 2, + "desc": "오버랩일 경우 XPATH구문에서 Type속성값 16으로 변경, 그리고 ClipIndex값은 트랜지션이 끝나는 지점 이미지의 ClipIndex값을 가지게 되어 다음 순서의 이미지로 변경해주어야한다." + }, + "22": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@Name", + "ele2": "//CRCUnitArr[@Name='{search}']/@Name", + "type": "opening", + "search": "자연 놀이터 (Nature Playground)", + "value": "자연 놀이터 (Nature Playground)", + "point": 3 + }, + "23": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", + "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID102", + "search": "자연 놀이터 (Nature Playground)", + "type": "opening", + "value": "바탕체", + "point": 2 + }, + "24": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", + "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool[@Type='1']/GCUnit/@VID101", + "search": "자연 놀이터 (Nature Playground)", + "type": "opening", + "value": "140", + "point": 2 + }, + "25": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", + "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool/GCUnit[@Type='4']/@VID100", + "search": "자연 놀이터 (Nature Playground)", + "type": "opening", + "value": "-12808648", + "point": 2 + }, + "26": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='2']/@*[name()='VID100' or name()='VID101']", + "ele2": "//CRCUnitArr[@Name='{search}']//GCUnitPool/GCUnit[@Type='2']/@*[name()='VID100' or name()='VID101']", + "search": "자연 놀이터 (Nature Playground)", + "type": "opening", + "value": ["0.30000001", "-13107457"], + "point": 2 + }, + "27": { + "ele": "//CROwneUnit[{subtitleIndex}]/CRCUnitArr/@*[name()='VID505' or name()='VID507']", + "ele2": "//CRCUnitArr[@Name='{search}']/@*[name()='VID505' or name()='VID507']", + "search": "자연 놀이터 (Nature Playground)", + "type": "opening", + "value": ["14", "2"], + "point": 3 + }, + "28": { + "ele": "sum(//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][{subtitleOrder}]/preceding-sibling::CRTrackClip/@Length)", + "ele2": "sum(//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][@ClipIndex={textClipIndex}]/preceding-sibling::CRTrackClip/@Length)", + "search": "자연 놀이터 (Nature Playground)", + "type": "opening", + "value": 0, + "point": 2 + }, + "29": { + "ele": "//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][{subtitleOrder}]/@Length", + "ele2": "//CRTrackList[@Name='텍스트' or @Name='비디오2']/CRTrackClip[not(@ClipIndex='-1')][@ClipIndex={textClipIndex}]/@Length", + "search": "자연 놀이터 (Nature Playground)", + "type": "opening", + "value": "120", + "point": 2 + }, + "30": { + "ele": "//CRTrackList[@Name='오디오1'][@Count>='1']/CRTrackClip[1][not(@ClipIndex='-1')]", + "point": 2 + }, + "31": { + "ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']/CRTrackClip[@Length='840']", + "point": 2 + }, + "32": { + "ele": "//CRTrackArr/CRAudioTrackArr/CRTrackList[@Name='오디오1']//CRFilter[@Type='2'][@ID='1'][@VID8='60']", + "point": 2 + }, + "33": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "4": { + "1": { + "type": "multi", + "ele": "//Document/Width/@value | //Document/Height/@value", + "value": ["650", "350"], + "point": 5, + "desc": "캔버스 사이즈 650*350" + }, + "2": { + "ele": "none", + "point": 5, + "desc": "자유 변형 문항은 채점 불가" + }, + "3": { + "type": "isExist", + "ele": "//Layer/Name/@value", + "value": "Flower", + "point": 5, + "desc": "Flower 레이어가 있는지 여부 체크" + }, + "4": { + "type": "multiValue", + "ele": "//Layer[Name[@value='{layer}']]/Effects/Item[EffectData/{option}]/Name/@value | //Layer[Name[@value='{layer}']]/Effects/Item/EffectData/{option}/@value", + "layer": "Flower", + "option": "VibranceValue", + "value": ["39", "생동감"], + "point": 5, + "desc": "Flower 레이어의 효과 체크" + }, + "5": { + "ele": "none", + "point": 6, + "desc": "올가미 도구/이미지 문항은 채점 불가" + }, + "6": { + "type": "exists", + "ele": "//Layer/Effects/Item/Name/@value", + "value": "세피아", + "point": 6, + "desc": "세피아 효과가 있는지 여부 체크" + }, + "7": { + "type": "exact", + "ele": "//Layer/Shapes/Shape/shape_type/@value", + "value": "ELLIPSE", + "point": 3, + "desc": "레이어 쉐이프 타입이 타원인지 체크" + }, + "8": { + "type": "size", + "ele": "//Layer//op_points", + "value": { + "width": 120, + "height": 120 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "9": { + "type": "color", + "ele": "//Layer//Shape[contains(draw_type/@value, 'Interior')]/secondary_color/@value", + "value": "7097bb", + "point": 6, + "desc": "색상 코드 비교 시 소문자로 입력할 것" + }, + "10": { + "type": "multiValue", + "ele": "//Layer/BlendOp/@value | //Layer/Opacity/@value", + "value": ["반사", "80"], + "point": 6, + "desc": "혼합모드(색 회피율, 불투명도 : 80)" + }, + "11": { + "ele": "none", + "point": 0, + "desc": "기본설정" + }, + "12": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "5": { + "1": { + "type": "multi", + "ele": "//Document/Width/@value | //Document/Height/@value", + "value": ["650", "450"], + "point": 5, + "desc": "캔버스 사이즈 650*450" + }, + "2": { + "ele": "none", + "point": 5, + "desc": "배경색 문항은 채점 불가" + }, + "3": { + "type": "exists", + "ele": "//Layer/MaskOpType/@value", + "value": "Layering", + "point": 6 + }, + "4": { + "ele": "none", + "point": 6, + "desc": "가로방향 흐릿하게 문항은 채점 불가" + }, + "5": { + "type": "exists", + "ele": "//Layer//shape_type/@value", + "value": "ROUNDED_RECTANGLE", + "point": 3 + }, + "6": { + "type": "size", + "ele": "//Layer//op_points", + "value": { + "width": 400, + "height": 60 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "7": { + "type": "gradient", + "ele": "//Layer/Shapes/Shape", + "startColor": "gradient_start_color/@value", + "endColor": "gradient_end_color/@value", + "value": { + "startColor": "ffe000", + "endColor": "34a159" + }, + "point": 6 + }, + "8": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/lines/Item/@value", + "value": "흰 꽃 사이 노란 꽃", + "point": 5 + }, + "9": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Name/@value", + "value": "맑은 고딕", + "point": 3 + }, + "10": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/{style}/@value", + "style": "Italic", + "value": "True", + "point": 3 + }, + "11": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Size/@value", + "value": "30", + "point": 3 + }, + "12": { + "type": "color", + "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Interior')]/secondary_color/@value", + "value": "b46ef8", + "point": 3, + "desc": "색상 코드 비교 시 소문자로 입력할 것" + }, + "13": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/outline_peninfo/Width/@value", + "value": "7", + "point": 3 + }, + "14": { + "type": "color", + "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Outline')]/primary_color/@value", + "value": "ffffff", + "point": 3, + "desc": "색상 코드 비교 시 소문자로 입력할 것" + }, + "15": { + "ele": "//Layer[MaskOpType/@value='Clipping'][last()]", + "point": 6, + "desc": "클리핑 마스크 항목은 별도 레이어로 추가되고 해당 속성을 추가해놓은 레이어가 있는지 여부 체크 함" + }, + "16": { + "type": "exists", + "ele": "//Layer/Shapes/Shape/shape_type/@value", + "value": "RECTANGLE", + "point": 3 + }, + "17": { + "type": "size", + "ele": "//Layer//op_points", + "value": { + "width": 150, + "height": 150 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "18": { + "type": "exists", + "ele": "//Layer//outline_peninfo/Width/@value", + "value": "7", + "point": 3 + }, + "19": { + "type": "color", + "ele": "//Layer//Shape[contains(draw_type/@value, 'Outline')]/primary_color/@value", + "value": "e8e88e", + "point": 3, + "desc": "색상 코드 비교 시 소문자로 입력할 것(채우기:secondary_color, 외곽선:primary_color)" + }, + "20": { + "type": "shadow", + "ele": { + "shadow": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]", + "width": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_width/@value", + "distance": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_distance/@value", + "blur": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_blur/@value", + "angle": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_angle/@value" + }, + "value": { + "width": "3", + "distance": "5", + "blur": "1", + "angle": "320" + }, + "point": 5, + "desc": "그림자 속성이 있는 경우 그림자 속성의 너비, 거리, 흐림 정도, 각도를 비교하여 정답 채점" + }, + "21": { + "ele": "none", + "point": 0, + "desc": "기본설정" + }, + "22": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + } +} diff --git a/DIC_2505B copy.json b/DIC_2505B copy.json deleted file mode 100644 index 9095736..0000000 --- a/DIC_2505B copy.json +++ /dev/null @@ -1,729 +0,0 @@ -{ - "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": "size", - "value": { - "width": 65, - "height": 45 - }, - "point": 4 - }, - "9": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } - }, - "1": { - "1": { - "ele": "none", - "point": 0 - }, - "2": { - "ele": "none", - "point": 0 - }, - "3": { - "ele": "none", - "point": 0 - }, - "4": { - "ele": "$.children[?(@.name=='한옥')].name", - "value": "한옥", - "point": 4 - }, - "5": { - "ele": "none", - "point": 0 - }, - "6": { - "ele": "$.children[?(@.name=='Traditional Park')].name", - "value": "Traditional Park", - "point": 4 - }, - "7": { - "ele": "$.children[?(@.name=='Traditional Park')].text.font.names[0]", - "type": "font", - "value": "Arial", - "point": 2 - }, - "8": { - "ele": "$.children[?(@.name=='Traditional Park')].text.font.names[0]", - "value": "Arial-BoldItalicMT", - "point": 2 - }, - "9": { - "ele": "$.children[?(@.name=='Traditional Park')].text.font.sizes[0]", - "value": 48, - "point": 2 - }, - "10": { - "ele": "$.children[?(@.name=='Traditional Park')].text.font.colors[0]", - "type": "color", - "value": "017e86", - "point": 2 - }, - "11": { - "ele": "none", - "point": 0 - }, - "12": { - "ele": "none", - "point": 0 - }, - "13": { - "ele": "none", - "point": 0 - }, - "14": { - "ele": "$.children[?(@.name=='전통 문화 공원')].name", - "value": "전통 문화 공원", - "point": 4 - }, - "15": { - "ele": "$.children[?(@.name=='전통 문화 공원')].text.font.names[0]", - "type": "font", - "value": "GungsuhChe", - "point": 2, - "desc": { - "돋움체": "DotumChe", - "궁서체": "GungsuhChe", - "굴림체": "GulimChe", - "휴먼옛체": "YetR" - } - }, - "16": { - "ele": "$.children[?(@.name=='전통 문화 공원')].text.font.sizes[0]", - "value": 36, - "point": 2 - }, - "17": { - "ele": "$.children[?(@.name=='전통 문화 공원')].text.font.colors[0]", - "type": "color", - "value": "ffeeca", - "point": 2 - }, - "18": { - "ele": "none", - "point": 0 - }, - "19": { - "ele": "none", - "point": 0 - }, - "20": { - "ele": "none", - "point": 0 - }, - "21": { - "ele": "none", - "point": 0 - }, - "22": { - "ele": "$.children[?(@.name=='맷돌')].name", - "value": "맷돌", - "point": 4 - }, - "23": { - "ele": "none", - "point": 0 - }, - "24": { - "ele": "none", - "point": 0 - }, - "25": { - "ele": "none", - "point": 0 - }, - "26": { - "ele": "$[?(@.width == 65 && @.height == 35)]", - "type": "size", - "value": { - "width": 65, - "height": 35 - }, - "point": 5 - }, - "27": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } - }, - "2": { - "1": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[not(@Length<='5' and @ClipLength='-1')]/@ClipIndex", - "type": "mediaOrder", - "value": [ - "동영상.mp4", - "이미지2.jpg", - "이미지3.jpg", - "이미지1.jpg" - ], - "point": 4, - "desc": "비디오1 트랙에 있는 클립의 ClipIndex값을 기준으로 CRClipArr에서 Path값을 가져와서 정답 채점, 클립의 ClipIndex값이 -1인 경우와 길이가 5프레임 이하인 경우는 제외한다." - }, - "2": { - "ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed", - "type": "oneAnswer", - "value": { - "speed": "120" - }, - "point": 2, - "desc": "100당 1배속 / 130 = 1.3배속" - }, - "3": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", - "type": "startEnd", - "media": "동영상.mp4", - "value": { - "start": "0", - "end": "380" - }, - "point": 2, - "desc": "시작시간과 재생시간 정답값 입력, 3번문항은 '동영상.mp4' 클립의 길이를 확인하는 문항이므로 media는 수정할 필요가 없다." - }, - "4": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "effect", - "media": "동영상.mp4", - "value": { - "ID": "70", - "VID100": "30", - "VID101": "20" - }, - "point": 3, - "desc": "value값의 키값(VID___)은 이펙트의 속성종류에 따라 변경되므로 채점기준표작성시 확인 필요" - }, - "5": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", - "search": "청량하고 시원한 폭포", - "type": "video.Text", - "value": "청량하고 시원한 폭포", - "point": 3 - }, - "6": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", - "search": "청량하고 시원한 폭포", - "type": "video.Text", - "value": "돋움체", - "point": 2 - }, - "7": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", - "search": "청량하고 시원한 폭포", - "type": "video.Text", - "value": "120", - "point": 2 - }, - "8": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", - "search": "청량하고 시원한 폭포", - "type": "video.Text.Color", - "value": "1db0f1", - "point": 2, - "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" - }, - "9": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr/@*[name()='VID600' or name()='VID601']", - "search": "청량하고 시원한 폭포", - "type": "video.Location", - "value": [ - "0.27395833", - "0.9222222" - ], - "point": 2, - "desc": "정답 파일의 자막 좌표를 기준으로 프로그램 내부적으로 0.1까지 오차를 허용한다" - }, - "10": { - "ele": "", - "search": "청량하고 시원한 폭포", - "type": "video.StartTime", - "value": 170, - "point": 2, - "desc": "내부적으로 자막의 시작시간과 길이를 계산" - }, - "11": { - "ele": "", - "search": "청량하고 시원한 폭포", - "type": "video.Length", - "value": 150, - "point": 2, - "desc": "내부적으로 자막의 시작시간과 길이를 계산" - }, - "12": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Mute", - "type": "Mute", - "media": "동영상.mp4", - "value": "1", - "point": 2 - }, - "13": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", - "type": "imageLength", - "media": "이미지2.jpg", - "value": "150", - "point": 2 - }, - "14": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "imageOverlay", - "media": "이미지2.jpg", - "value": { - "ID": "103", - "VID102": "7" - }, - "point": 2 - }, - "15": { - "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", - "type": "clipTransition", - "media": "이미지2.jpg", - "value": { - "ID": "11", - "Range": "500:530", - "Type": "2" - }, - "point": 2, - "desc": "오버랩일 경우 Type속성값 16으로 변경" - }, - "16": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", - "type": "imageLength", - "media": "이미지3.jpg", - "value": "150", - "point": 2 - }, - "17": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "imageOverlay", - "media": "이미지3.jpg", - "value": { - "ID": "184", - "VID102": "30" - }, - "point": 2 - }, - "18": { - "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", - "type": "clipTransition", - "media": "이미지3.jpg", - "value": { - "ID": "19", - "Range": "650:680", - "Type": "2" - }, - "point": 2, - "desc": "오버랩일 경우 Type속성값 16으로 변경" - }, - "19": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", - "type": "imageLength", - "media": "이미지1.jpg", - "value": "180", - "point": 2 - }, - "20": { - "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "imageOverlay", - "media": "이미지1.jpg", - "value": { - "ID": "67", - "VID102": "30" - }, - "point": 2 - }, - "21": { - "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", - "type": "clipTransition", - "media": "이미지1.jpg", - "value": { - "ID": "10", - "Range": "800:860", - "Type": "2" - }, - "point": 2, - "desc": "오버랩일 경우 Type속성값 16으로 변경" - }, - "22": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", - "search": "전통 공원 (Traditional Park)", - "type": "video.Text", - "value": "전통 공원 (Traditional Park)", - "point": 3 - }, - "23": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", - "search": "전통 공원 (Traditional Park)", - "type": "video.Text", - "value": "궁서체", - "point": 2 - }, - "24": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", - "search": "전통 공원 (Traditional Park)", - "type": "video.Text", - "value": "140", - "point": 2 - }, - "25": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", - "search": "전통 공원 (Traditional Park)", - "type": "video.Text.Color", - "value": "fd5721", - "point": 2, - "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" - }, - "26": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='2']", - "search": "전통 공원 (Traditional Park)", - "type": "video.Text.Outline", - "value": { - "width": "30", - "color": "fff9c4" - }, - "point": 2, - "desc": "두께는 XML에서는 소수점으로 표기되지만, 프로그램 내부적으로 변환하여 사용하므로 현재 파일에서는 정수로 작성" - }, - "27": { - "ele": "//CROwneUnit[{index}]/CRCUnitArr", - "search": "전통 공원 (Traditional Park)", - "type": "opening.Text.FadeInEffect", - "value": { - "ID": "4", - "PlayTime": "2" - }, - "point": 3, - "desc": "오프닝자막의 나타나기 효과를 확인하는 문항. id속성은 VID505, playtime속성은 VID507으로 XML 내부에 표기되어 있다." - }, - "28": { - "ele": "", - "search": "전통 공원 (Traditional Park)", - "type": "opening.StartTime", - "value": 0, - "point": 2, - "desc": "오프닝자막의 시작시간 value 속성만 수정" - }, - "29": { - "ele": "", - "search": "전통 공원 (Traditional Park)", - "type": "opening.Length", - "value": 120, - "point": 2 - }, - "30": { - "ele": "", - "type": "audio.StartTime", - "media": "음악.mp3", - "value": 0, - "point": 2 - }, - "31": { - "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", - "type": "audio.EndTime", - "media": "음악.mp3", - "value": 810, - "point": 2 - }, - "32": { - "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", - "type": "audio.Effect", - "media": "음악.mp3", - "value": { - "ID": "1", - "PlayTime": "90" - }, - "point": 2, - "desc": "ID속성-페이드인:0 / 페이드아웃:1" - }, - "33": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } - }, - "4": { - "1": { - "type": "multi", - "ele": "//Document/Width/@value | //Document/Height/@value", - "value": [ - "650", - "350" - ], - "point": 5, - "desc": "캔버스 사이즈 650*350" - }, - "2": { - "ele": "none", - "point": 5, - "desc": "자유 변형 문항은 채점 불가" - }, - "3": { - "type": "isExist", - "ele": "//Layer/Name/@value", - "value": "Flower", - "point": 5, - "desc": "Flower 레이어가 있는지 여부 체크" - }, - "4": { - "type": "multiValue", - "ele": "//Layer[Name[@value='{layer}']]/Effects/Item[EffectData/{option}]/Name/@value | //Layer[Name[@value='{layer}']]/Effects/Item/EffectData/{option}/@value", - "layer": "Flower", - "option": "VibranceValue", - "value": [ - "39", - "생동감" - ], - "point": 5, - "desc": "Flower 레이어의 효과 체크" - }, - "5": { - "ele": "none", - "point": 6, - "desc": "올가미 도구/이미지 문항은 채점 불가" - }, - "6": { - "type": "exists", - "ele": "//Layer/Effects/Item/Name/@value", - "value": "세피아", - "point": 6, - "desc": "세피아 효과가 있는지 여부 체크" - }, - "7": { - "type": "exact", - "ele": "//Layer/Shapes/Shape/shape_type/@value", - "value": "ELLIPSE", - "point": 3, - "desc": "레이어 쉐이프 타입이 타원인지 체크" - }, - "8": { - "type": "size", - "ele": "//Layer//op_points", - "value": { - "width": 120, - "height": 120 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "9": { - "type": "color", - "ele": "//Layer//Shape[contains(draw_type/@value, 'Interior')]/secondary_color/@value", - "value": "7097bb", - "point": 6, - "desc": "색상 코드 비교 시 소문자로 입력할 것" - }, - "10": { - "type": "multiValue", - "ele": "//Layer/BlendOp/@value | //Layer/Opacity/@value", - "value": [ - "반사", - "80" - ], - "point": 6, - "desc": "혼합모드(색 회피율, 불투명도 : 80)" - }, - "11": { - "ele": "none", - "point": 0, - "desc": "기본설정" - }, - "12": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } - }, - "5": { - "1": { - "type": "multi", - "ele": "//Document/Width/@value | //Document/Height/@value", - "value": [ - "650", - "450" - ], - "point": 5, - "desc": "캔버스 사이즈 650*450" - }, - "2": { - "ele": "none", - "point": 5, - "desc": "배경색 문항은 채점 불가" - }, - "3": { - "type": "exists", - "ele": "//Layer/MaskOpType/@value", - "value": "Layering", - "point": 6 - }, - "4": { - "ele": "none", - "point": 6, - "desc": "가로방향 흐릿하게 문항은 채점 불가" - }, - "5": { - "type": "exists", - "ele": "//Layer//shape_type/@value", - "value": "ROUNDED_RECTANGLE", - "point": 3 - }, - "6": { - "type": "size", - "ele": "//Layer//op_points", - "value": { - "width": 400, - "height": 60 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "7": { - "type": "gradient", - "ele": "//Layer/Shapes/Shape", - "startColor": "gradient_start_color/@value", - "endColor": "gradient_end_color/@value", - "value": { - "startColor": "ffe000", - "endColor": "34a159" - }, - "point": 6 - }, - "8": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/lines/Item/@value", - "value": "흰 꽃 사이 노란 꽃", - "point": 5 - }, - "9": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Name/@value", - "value": "맑은 고딕", - "point": 3 - }, - "10": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/{style}/@value", - "style": "Italic", - "value": "True", - "point": 3 - }, - "11": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Size/@value", - "value": "30", - "point": 3 - }, - "12": { - "type": "color", - "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Interior')]/secondary_color/@value", - "value": "b46ef8", - "point": 3, - "desc": "색상 코드 비교 시 소문자로 입력할 것" - }, - "13": { - "type": "exists", - "ele": "//Layer//Shape[shape_type/@value='TEXT']/outline_peninfo/Width/@value", - "value": "7", - "point": 3 - }, - "14": { - "type": "color", - "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Outline')]/primary_color/@value", - "value": "ffffff", - "point": 3, - "desc": "색상 코드 비교 시 소문자로 입력할 것" - }, - "15": { - "ele": "//Layer[MaskOpType/@value='Clipping'][last()]", - "point": 6, - "desc": "클리핑 마스크 항목은 별도 레이어로 추가되고 해당 속성을 추가해놓은 레이어가 있는지 여부 체크 함" - }, - "16": { - "type": "exists", - "ele": "//Layer/Shapes/Shape/shape_type/@value", - "value": "RECTANGLE", - "point": 3 - }, - "17": { - "type": "size", - "ele": "//Layer//op_points", - "value": { - "width": 150, - "height": 150 - }, - "point": 3, - "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" - }, - "18": { - "type": "exists", - "ele": "//Layer//outline_peninfo/Width/@value", - "value": "7", - "point": 3 - }, - "19": { - "type": "color", - "ele": "//Layer//Shape[contains(draw_type/@value, 'Outline')]/primary_color/@value", - "value": "e8e88e", - "point": 3, - "desc": "색상 코드 비교 시 소문자로 입력할 것(채우기:secondary_color, 외곽선:primary_color)" - }, - "20": { - "type": "shadow", - "ele": { - "shadow": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]", - "width": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_width/@value", - "distance": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_distance/@value", - "blur": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_blur/@value", - "angle": "//Layer//Shape[contains(draw_type/@value, 'Shadow')]/shadow_angle/@value" - }, - "value": { - "width": "3", - "distance": "5", - "blur": "1", - "angle": "320" - }, - "point": 5, - "desc": "그림자 속성이 있는 경우 그림자 속성의 너비, 거리, 흐림 정도, 각도를 비교하여 정답 채점" - }, - "21": { - "ele": "none", - "point": 0, - "desc": "기본설정" - }, - "22": { - "ele": "none", - "point": 0, - "desc": "파일명 확인" - } - } -} \ No newline at end of file diff --git a/DIC_2505B.json b/DIC_2505B.json index b457875..f2d8dfb 100644 --- a/DIC_2505B.json +++ b/DIC_2505B.json @@ -501,7 +501,7 @@ "layer": "Flower", "option": "VibranceValue", "value": [ - "39", + "40", "생동감" ], "point": 5, diff --git a/DIC_곰픽채점기준표.json b/DIC_곰픽채점기준표.json new file mode 100644 index 0000000..58030f2 --- /dev/null +++ b/DIC_곰픽채점기준표.json @@ -0,0 +1,737 @@ +{ + "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": "size", + "value": { + "width": 65, + "height": 45 + }, + "point": 4 + }, + "9": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "1": { + "1": { + "ele": "none", + "point": 0 + }, + "2": { + "ele": "none", + "point": 0 + }, + "3": { + "ele": "none", + "point": 0 + }, + "4": { + "ele": "$.children[?(@.name=='꽃잎들')].name", + "value": "꽃잎들", + "point": 4 + }, + "5": { + "ele": "none", + "point": 0 + }, + "6": { + "ele": "$.children[?(@.name=='Flower Rock')].name", + "value": "Flower Rock", + "point": 4 + }, + "7": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.names[0]", + "type": "font", + "value": "Arial", + "point": 2 + }, + "8": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.names[0]", + "value": "Arial-BoldItalicMT", + "point": 2 + }, + "9": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.sizes[0]", + "value": 48, + "point": 2 + }, + "10": { + "ele": "$.children[?(@.name=='Flower Rock')].text.font.colors[0]", + "type": "color", + "value": "d6f592", + "point": 2 + }, + "11": { + "ele": "none", + "point": 0 + }, + "12": { + "ele": "none", + "point": 0 + }, + "13": { + "ele": "none", + "point": 0 + }, + "14": { + "ele": "$.children[?(@.name=='꽃과 바위')].name", + "value": "꽃과 바위", + "point": 4 + }, + "15": { + "ele": "$.children[?(@.name=='꽃과 바위')].text.font.names[0]", + "type": "font", + "value": "GungsuhChe", + "point": 2, + "desc": { + "돋움체": "DotumChe", + "궁서체": "GungsuhChe", + "굴림체": "GulimChe", + "휴먼옛체": "YetR" + } + }, + "16": { + "ele": "$.children[?(@.name=='꽃과 바위')].text.font.sizes[0]", + "value": 36, + "point": 2 + }, + "17": { + "ele": "$.children[?(@.name=='꽃과 바위')].text.font.colors[0]", + "type": "color", + "value": "0d17d5", + "point": 2 + }, + "18": { + "ele": "none", + "point": 0 + }, + "19": { + "ele": "none", + "point": 0 + }, + "20": { + "ele": "none", + "point": 0 + }, + "21": { + "ele": "none", + "point": 0 + }, + "22": { + "ele": "$.children[?(@.name=='노랑꽃')].name", + "value": "노랑꽃", + "point": 4 + }, + "23": { + "ele": "none", + "point": 0 + }, + "24": { + "ele": "none", + "point": 0 + }, + "25": { + "ele": "none", + "point": 0 + }, + "26": { + "ele": "$[?(@.width == 65 && @.height == 35)]", + "type": "size", + "value": { + "width": 65, + "height": 35 + }, + "point": 5 + }, + "27": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "2": { + "1": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[not(@Length<='5' and @ClipLength='-1')]/@ClipIndex", + "type": "mediaOrder", + "value": ["동영상.mp4", "이미지3.jpg", "이미지1.jpg", "이미지2.jpg"], + "point": 4, + "desc": "비디오1 트랙에 있는 클립의 ClipIndex값을 기준으로 CRClipArr에서 Path값을 가져와서 정답 채점, 클립의 ClipIndex값이 -1인 경우와 길이가 5프레임 이하인 경우는 제외한다." + }, + "2": { + "ele": "/CROASTERP/CRTrackArr[1]/CRVideoTrackArr[1]/CRTrackList[1]/CRTrackClip[1]/@Speed", + "type": "oneAnswer", + "value": { + "speed": "140" + }, + "point": 2, + "desc": "100당 1배속 / 130 = 1.3배속" + }, + "3": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", + "type": "startEnd", + "media": "동영상.mp4", + "value": { + "start": "0", + "end": "370" + }, + "point": 2, + "desc": "시작시간과 재생시간 정답값 입력, 3번문항은 '동영상.mp4' 클립의 길이를 확인하는 문항이므로 media는 수정할 필요가 없다." + }, + "4": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "effect", + "media": "동영상.mp4", + "value": { + "ID": "44", + "VID100": "8", + "VID103": "0.89999998" + }, + "point": 3, + "desc": "value값의 키값(VID___)은 이펙트의 속성종류에 따라 변경되므로 채점기준표작성시 확인 필요" + }, + "5": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", + "search": "화단의 꽃들", + "type": "video.Text", + "value": "화단의 꽃들", + "point": 3 + }, + "6": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", + "search": "화단의 꽃들", + "type": "video.Text", + "value": "돋움체", + "point": 2 + }, + "7": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", + "search": "화단의 꽃들", + "type": "video.Text", + "value": "110", + "point": 2 + }, + "8": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", + "search": "화단의 꽃들", + "type": "video.Text.Color", + "value": "ff531b", + "point": 2, + "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" + }, + "9": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr/@*[name()='VID600' or name()='VID601']", + "search": "화단의 꽃들", + "type": "video.Location", + "value": ["0.38333333", "0.92962962"], + "point": 2, + "desc": "정답 파일의 자막 좌표를 기준으로 프로그램 내부적으로 0.1까지 오차를 허용한다" + }, + "10": { + "ele": "", + "search": "화단의 꽃들", + "type": "video.StartTime", + "value": 170, + "point": 2, + "desc": "내부적으로 자막의 시작시간과 길이를 계산" + }, + "11": { + "ele": "", + "search": "화단의 꽃들", + "type": "video.Length", + "value": 150, + "point": 2, + "desc": "내부적으로 자막의 시작시간과 길이를 계산" + }, + "12": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Mute", + "type": "Mute", + "media": "동영상.mp4", + "value": "1", + "point": 2 + }, + "13": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", + "type": "imageLength", + "media": "이미지3.jpg", + "value": "180", + "point": 2 + }, + "14": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "imageOverlay", + "media": "이미지3.jpg", + "value": { + "ID": "67", + "VID102": "40" + }, + "point": 2, + "desc": "오버레이 속성 키값(VID10X) 확인하고 변경" + }, + "15": { + "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", + "type": "clipTransition", + "media": "이미지3.jpg", + "value": { + "ID": "10", + "Range": "490:550", + "Type": "2" + }, + "point": 2, + "desc": "오버랩일 경우 Type속성값 16으로 변경" + }, + "16": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", + "type": "imageLength", + "media": "이미지1.jpg", + "value": "180", + "point": 2 + }, + "17": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "imageOverlay", + "media": "이미지1.jpg", + "value": { + "ID": "103", + "VID102": "7" + }, + "point": 2, + "desc": "오버레이 속성 키값(VID10X) 확인하고 변경" + }, + "18": { + "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", + "type": "clipTransition", + "media": "이미지1.jpg", + "value": { + "ID": "12", + "Range": "670:730", + "Type": "2" + }, + "point": 2, + "desc": "오버랩일 경우 Type속성값 16으로 변경" + }, + "19": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']/@Length", + "type": "imageLength", + "media": "이미지2.jpg", + "value": "150", + "point": 2 + }, + "20": { + "ele": "//CRTrackList[@Name='비디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "imageOverlay", + "media": "이미지2.jpg", + "value": { + "ID": "102", + "VID101": "3" + }, + "point": 2, + "desc": "오버레이 속성 키값(VID10X) 확인하고 변경" + }, + "21": { + "ele": "//CRTransFilter[@ClipIndex='{CRTrackClipIndex}']", + "type": "clipTransition", + "media": "이미지2.jpg", + "value": { + "ID": "0", + "Range": "850:880", + "Type": "2" + }, + "point": 2, + "desc": "오버랩일 경우 Type속성값 16으로 변경" + }, + "22": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr/@Name", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text", + "value": "아름다운 꽃 축제 (Happy Flower Festival)", + "point": 3 + }, + "23": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID102", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text", + "value": "궁서체", + "point": 2 + }, + "24": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool[@Type='1']/GCUnit/@VID101", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text", + "value": "140", + "point": 2 + }, + "25": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='4']/@VID100", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text.Color", + "value": "ec008c", + "point": 2, + "desc": "컬러값은 RGB로 입력한다, [대소문자, #]허용 (#FFFFFF, ffffff 두 값 모두 허용)" + }, + "26": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr//GCUnitPool/GCUnit[@Type='2']", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "video.Text.Outline", + "value": { + "width": "40", + "color": "fff9c4" + }, + "point": 2, + "desc": "두께는 XML에서는 소수점으로 표기되지만, 프로그램 내부적으로 변환하여 사용하므로 현재 파일에서는 정수로 작성" + }, + "27": { + "ele": "//CROwneUnit[{index}]/CRCUnitArr", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "opening.Text.FadeInEffect", + "value": { + "ID": "14", + "PlayTime": "2" + }, + "point": 3, + "desc": "오프닝자막의 나타나기 효과를 확인하는 문항. id속성은 VID505, playtime속성은 VID507으로 XML 내부에 표기되어 있다." + }, + "28": { + "ele": "", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "opening.StartTime", + "value": 0, + "point": 2, + "desc": "오프닝자막의 시작시간 value 속성만 수정" + }, + "29": { + "ele": "", + "search": "아름다운 꽃 축제 (Happy Flower Festival)", + "type": "opening.Length", + "value": 120, + "point": 2 + }, + "30": { + "ele": "", + "type": "audio.StartTime", + "media": "음악.mp3", + "value": 0, + "point": 2 + }, + "31": { + "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']", + "type": "audio.EndTime", + "media": "음악.mp3", + "value": "870", + "point": 2 + }, + "32": { + "ele": "//CRTrackList[@Name='오디오1']/CRTrackClip[@ClipIndex='{CRClipIndex}']//CRFilter", + "type": "audio.Effect", + "media": "음악.mp3", + "value": { + "ID": "1", + "PlayTime": "60" + }, + "point": 2, + "desc": "ID속성-페이드인:0 / 페이드아웃: 1" + }, + "33": { + "ele": "none", + "point": 0, + "desc": "파일명 확인" + } + }, + "4": { + "1": { + "type": "canvas.Size", + "ele": "//Document/Width/@value | //Document/Height/@value", + "value": ["650", "350"], + "point": 5, + "desc": "캔버스 사이즈 650*350" + }, + "2": { + "type": "none", + "ele": "", + "point": 5, + "desc": "자유 변형 문항은 채점 불가" + }, + "3": { + "type": "layer.exists", + "ele": "//Layer/Name/@value", + "value": "Flower", + "point": 5, + "desc": "Flower 레이어가 있는지 여부 체크" + }, + "4": { + "type": "layer.Effects", + "ele": "//Layer[Name[@value='{search}']]/Effects/Item", + "search": "Flower", + "value": { + "name": "생동감", + "option": { + "생동감": "40" + } + }, + "point": 5, + "desc": { + "흑백": "강도", + "밝기/대비": ["밝기", "대비"], + "노출": "노출", + "색조/채도": ["색조", "채도", "명도"], + "감마":["리프트","감마","게인"], + "세피아":["U","V"], + "생동감": "생동감" + } + }, + "5": { + "type": "none", + "ele": "", + "point": 6, + "desc": "올가미 도구/이미지 문항은 채점 불가" + }, + "6": { + "type": "exists", + "ele": "//Layer/Effects/Item/Name/@value", + "value": "세피아", + "point": 6, + "desc": "세피아 효과가 있는지 여부 체크" + }, + "7": { + "type": "exists", + "ele": "//Layer/Shapes/Shape/shape_type/@value", + "value": "ELLIPSE", + "point": 3, + "desc": "레이어 쉐이프 타입이 타원인지 체크" + }, + "8": { + "type": "shape.size", + "ele": "//Layer//op_points", + "value": { + "width": 120, + "height": 120 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "9": { + "type": "shape.color", + "ele": "//Layer//Shape[contains(draw_type/@value, 'Interior')]/secondary_color/@value", + "value": "7097BB", + "point": 6, + "desc": "" + }, + "10": { + "type": "layer.blend.opacity", + "ele": "//Layer", + "value": { + "BlendOp": "반사", + "Opacity": "80" + }, + "point": 6 + }, + "11": { + "type": "none", + "ele": "", + "point": 0, + "desc": "기본설정" + }, + "12": { + "type": "none", + "ele": "", + "point": 0, + "desc": "파일명 확인" + } + }, + "5": { + "1": { + "type": "canvas.Size", + "ele": "//Document/Width/@value | //Document/Height/@value", + "value": ["650", "450"], + "point": 5, + "desc": "캔버스 사이즈 650*450" + }, + "2": { + "type": "none", + "ele": "", + "point": 5, + "desc": "배경색 문항은 채점 불가" + }, + "3": { + "type": "exists", + "ele": "//Layer/MaskOpType/@value", + "value": "Layering", + "point": 6, + "desc": "레이어 마스크 설정 확인" + }, + "4": { + "type": "none", + "ele": "", + "point": 6, + "desc": "가로방향 흐릿하게 문항은 채점 불가" + }, + "5": { + "type": "exists", + "ele": "//Layer//shape_type/@value", + "value": "ROUNDED_RECTANGLE", + "point": 3 + }, + "6": { + "type": "shape.size", + "ele": "//Layer//op_points", + "value": { + "width": 400, + "height": 60 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "7": { + "type": "gradient.color", + "ele": "//Layer/Shapes/Shape", + "startColor": "gradient_start_color/@value", + "endColor": "gradient_end_color/@value", + "value": { + "startColor": "ffe000", + "endColor": "34A159" + }, + "point": 6 + }, + "8": { + "type": "text.exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/lines/Item/@value", + "value": "흰 꽃 사이 노란 꽃", + "point": 5 + }, + "9": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Name/@value", + "value": "맑은 고딕", + "point": 3 + }, + "10": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/{style}/@value", + "style": "Italic", + "value": "True", + "point": 3 + }, + "11": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/font/Size/@value", + "value": "30", + "point": 3 + }, + "12": { + "type": "text.color", + "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Interior')]/secondary_color/@value", + "value": "b46Ef8", + "point": 3 + }, + "13": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='TEXT']/outline_peninfo/Width/@value", + "value": "7", + "point": 3 + }, + "14": { + "type": "text.color", + "ele": "//Layer//Shape[shape_type/@value='TEXT'][contains(draw_type/@value, 'Outline')]/primary_color/@value", + "value": "ffffff", + "point": 3 + }, + "15": { + "type": "exists", + "ele": "//Layer/MaskOpType/@value", + "value": "Clipping", + "point": 6, + "desc": "클리핑 마스크 항목은 별도 레이어로 추가되고 해당 속성을 추가해놓은 레이어가 있는지 여부 체크 함" + }, + "16": { + "type": "exists", + "ele": "//Layer/Shapes/Shape/shape_type/@value", + "value": "RECTANGLE", + "point": 3, + "desc": { + "사각형": "RECTANGLE" + } + }, + "17": { + "type": "clipping.size", + "ele": "//Layer//Shape[shape_type/@value='{option}']//op_points", + "option": "RECTANGLE", + "value": { + "width": 150, + "height": 150 + }, + "point": 3, + "desc": "레이어 쉐이프 X, Y 좌표를 가지고 너비, 높이 계산하여 정답 채점" + }, + "18": { + "type": "exists", + "ele": "//Layer//Shape[shape_type/@value='{option}']/outline_peninfo/Width/@value", + "option": "RECTANGLE", + "value": "7", + "point": 3 + }, + "19": { + "type": "clipping.color", + "ele": "//Layer//Shape[shape_type/@value='{option}' and contains(draw_type/@value, 'Outline')]/primary_color/@value", + "option": "RECTANGLE", + "value": "e8e88e", + "point": 3, + "desc": "채우기:secondary_color, 외곽선:primary_color" + }, + "20": { + "type": "shadow", + "ele": "//Layer//Shape[shape_type/@value='{option}']", + "option": "RECTANGLE", + "value": { + "shadow": true, + "width": "3", + "distance": "5", + "blur": "1", + "angle": "320" + }, + "point": 5, + "desc": "그림자 속성이 있는 경우 그림자 속성의 너비, 거리, 흐림 정도, 각도를 비교하여 정답 채점" + }, + "21": { + "type": "none", + "ele": "", + "point": 0, + "desc": "기본설정" + }, + "22": { + "type": "none", + "ele": "", + "point": 0, + "desc": "파일명 확인" + } + } +} diff --git a/gpdpScoring.js b/gpdpScoring.js index eefc831..3f96986 100644 --- a/gpdpScoring.js +++ b/gpdpScoring.js @@ -192,29 +192,157 @@ function getGpdpScore(gpdpData, scoringJson, index) { } // [] - else if (type === "layer.Exists") { - const layerNameList = xpath.select(ele, gpdpXmlDoc); - const layerNames = layerNameList.map(layer => layer.value); - let isMatched = false + // else if (type === "layer.exists") { + // const layerNameList = xpath.select(ele, gpdpXmlDoc); + // const layerNames = layerNameList.map(layer => layer.value); + // let isMatched = false - // for (const layerName of layerNames) { - // if (layerName.trim().toLowerCase() === rightAnswer.trim().toLowerCase()) { - // userAnswer = layerName; - // isMatched = true; - // break; - // } - // } + // let result = findSimilarString(gpdpXmlDoc, rightAnswer, 0.8); + // if (result !== null) { + // userAnswer = result; + // isMatched = true; + // } - // if (isMatched) { - // totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); - // } + // if (isMatched) { + // totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult, { + // type: 'force-correct' + // }); + // } + // else { + // totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); + // } + // } - let result = findSimilarString(gpdpXmlDoc, rightAnswer, 0.8); - if (result !== null) { - userAnswer = result; - isMatched = true; + // [1-4] 사진1 > 조정 + else if (type === "layer.Effects") { + const effects = xpath.select(ele, gpdpXmlDoc); + + let isMatched = false; + for (const item of effects) { + const name = xpath.select1('Name/@value', item)?.value; + const effectData = xpath.select1(`EffectData`, item); + + // 동일한 이펙트 요소만 검사 + if (rightAnswer['name'] !== name) { + continue; + } + + userAnswer = { + name: name, + option: {}, + } + if (name === '흑백') { + const Intensity = xpath.select1('Intensity/@value', effectData)?.value; + + const optionKeys = Object.keys(rightAnswer['option']); + if (optionKeys.includes('강도')) userAnswer['option']['강도'] = Intensity; + } + else if (name === '밝기/대비') { + const brightness = xpath.select1('brightness/@value', effectData)?.value; + const contrast = xpath.select1('contrast/@value', effectData)?.value; + + const optionKeys = Object.keys(rightAnswer['option']); + if (optionKeys.includes('밝기')) userAnswer['option']['밝기'] = brightness; + if (optionKeys.includes('대비')) userAnswer['option']['대비'] = contrast; + } + else if (name === '노출') { + const ExposureValue = xpath.select1('ExposureValue/@value', effectData)?.value; + + const optionKeys = Object.keys(rightAnswer['option']); + if (optionKeys.includes('노출')) userAnswer['option']['노출'] = ExposureValue; + } + else if (name === '색조/채도') { + const hue = xpath.select1('hue/@value', effectData)?.value; + const saturation = xpath.select1('saturation/@value', effectData)?.value; + const lightness = xpath.select1('lightness/@value', effectData)?.value; + + const optionKeys = Object.keys(rightAnswer['option']); + if (optionKeys.includes('색조')) userAnswer['option']['색조'] = hue; + if (optionKeys.includes('채도')) userAnswer['option']['채도'] = saturation; + if (optionKeys.includes('명도')) userAnswer['option']['명도'] = lightness; + } + else if (name === '감마') { + const lift = xpath.select1('Lift/@value', effectData)?.value; + const gamma = xpath.select1('Gamma/@value', effectData)?.value; + const gain = xpath.select1('Gain/@value', effectData)?.value; + + const optionKeys = Object.keys(rightAnswer['option']); + if (optionKeys.includes('리프트')) userAnswer['option']['리프트'] = lift; + if (optionKeys.includes('감마')) userAnswer['option']['감마'] = gamma; + if (optionKeys.includes('게인')) userAnswer['option']['게인'] = gain; + } + else if (name === '세피아') { + const u = xpath.select1('U/@value', effectData)?.value; + const v = xpath.select1('V/@value', effectData)?.value; + + const optionKeys = Object.keys(rightAnswer['option']).map(key => key.toUpperCase()); + if (optionKeys.includes('U')) userAnswer['option']['U'] = u; + if (optionKeys.includes('V')) userAnswer['option']['V'] = v; + } + else if (name === '생동감') { + const vibranceValue = xpath.select1('VibranceValue/@value', effectData)?.value; + // 생동감 옵션값이 프로그램에서 적용한 값에 오차가 발생하는 경우가 있음 + // 곰픽>XML / 30>29 / 40>39 + // 설정한 값 그대로 적용되는 경우도 있어서 오차범위 2로 설정 + const userValue = parseInt(vibranceValue, 10); + const rightValue = parseInt(rightAnswer.option['생동감'], 10); + + if (Math.abs(rightValue - userValue) <= 2) { + const optionKeys = Object.keys(rightAnswer['option']); + if (optionKeys.includes('생동감')) { + userAnswer['option']['생동감'] = rightValue.toString(); + } + } + } + + for (const key in rightAnswer.option) { + // 속성값이 정답과 다른 경우가 있으면 오답처리 + if (rightAnswer.option[key] !== userAnswer.option[key]) { + isMatched = false; + break; + } + else { + isMatched = true; + } + } + + // 속성값이 하나라도 일치하지 않으면 오답 + if (isMatched === false) { + break; + } } + totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); + continue; + } + // + // else if (type === "exists") { + else if (type.includes("exists")) { + const existsValues = xpath.select(ele, gpdpXmlDoc); + let isMatched = false; + + for (const v of existsValues) { + userAnswer = v.value; + + if (type.includes('layer') || type.includes('text')) { + + // 공백, 대소문자 무시 + const cleanUserAnswer = userAnswer.replace(/\s+/g, '').toLowerCase(); + const cleanRightAnswer = rightAnswer.replace(/\s+/g, '').toLowerCase(); + + // 하나라도 일치하면 정답 + if (cleanUserAnswer === cleanRightAnswer) { + isMatched = true; + break; + } + } + else { + if (userAnswer === rightAnswer) { + isMatched = true; + break; + } + } + } if (isMatched) { totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult, { type: 'force-correct' @@ -223,506 +351,383 @@ function getGpdpScore(gpdpData, scoringJson, index) { else { totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); } + } - // [1-4] 사진1 > 조정 - else if (type === "layer.Effects") { - const effects = xpath.select(ele, gpdpXmlDoc); - let isMatched = false; - for (const item of effects) { - const name = xpath.select1('Name/@value', item)?.value; - const effectData = xpath.select1(`EffectData`, item); + // else if (type === "shape.size") { + else if (type.includes("size")) { + const items = xpath.select(ele, gpdpXmlDoc); + let isMatched = false; - // 동일한 이펙트 요소만 검사 - if (rightAnswer['name'] !== name) { - continue; + // 각 Item 요소별 x,y 좌표 시작점과 끝점의 거리를 계산해 정답과 비교 + for (const item of items) { + const x1 = Number(xpath.select1('Item[1]/X/@value', item)?.value); + const y1 = Number(xpath.select1('Item[1]/Y/@value', item)?.value); + + const x2 = Number(xpath.select1('Item[last()]/X/@value', item)?.value); + const y2 = Number(xpath.select1('Item[last()]/Y/@value', item)?.value); + + const width = Math.round(Math.abs(x2 - x1)); + const height = Math.round(Math.abs(y2 - y1)); + + userAnswer = { + width: width, + height: height, + }; + + // 하나라도 일치하면 정답 + if (JSON.stringify(userAnswer) == JSON.stringify(rightAnswer)) { + isMatched = true; + break; + } } - userAnswer = { - name: name, - option: {}, - } - if (name === '흑백') { - const Intensity = xpath.select1('Intensity/@value', effectData)?.value; + totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); + continue; + } - const optionKeys = Object.keys(rightAnswer['option']); - if (optionKeys.includes('강도')) userAnswer['option']['강도'] = Intensity; - } - else if (name === '밝기/대비') { - const brightness = xpath.select1('brightness/@value', effectData)?.value; - const contrast = xpath.select1('contrast/@value', effectData)?.value; + // [1-8] + else if (type.includes("color")) { + const items = xpath.select(ele, gpdpXmlDoc); + let normalizedAnswer = null; + let isMatched = false; - const optionKeys = Object.keys(rightAnswer['option']); - if (optionKeys.includes('밝기')) userAnswer['option']['밝기'] = brightness; - if (optionKeys.includes('대비')) userAnswer['option']['대비'] = contrast; - } - else if (name === '노출') { - const ExposureValue = xpath.select1('ExposureValue/@value', effectData)?.value; + for (const item of items) { + if (type.includes('gradient')) { + const startColorXpath = scoringData[key].startColor; + const endColorXpath = scoringData[key].endColor; - const optionKeys = Object.keys(rightAnswer['option']); - if (optionKeys.includes('노출')) userAnswer['option']['노출'] = ExposureValue; - } - else if (name === '색조/채도') { - const hue = xpath.select1('hue/@value', effectData)?.value; - const saturation = xpath.select1('saturation/@value', effectData)?.value; - const lightness = xpath.select1('lightness/@value', effectData)?.value; + const startColorRGB = xpath.select1(startColorXpath, item).value; + const endColorRGB = xpath.select1(endColorXpath, item).value; - const optionKeys = Object.keys(rightAnswer['option']); - if (optionKeys.includes('색조')) userAnswer['option']['색조'] = hue; - if (optionKeys.includes('채도')) userAnswer['option']['채도'] = saturation; - if (optionKeys.includes('명도')) userAnswer['option']['명도'] = lightness; - } - else if (name === '감마') { - const lift = xpath.select1('Lift/@value', effectData)?.value; - const gamma = xpath.select1('Gamma/@value', effectData)?.value; - const gain = xpath.select1('Gain/@value', effectData)?.value; + const startColor = parseColorToHex(startColorRGB); + const endColor = parseColorToHex(endColorRGB); - const optionKeys = Object.keys(rightAnswer['option']); - if (optionKeys.includes('리프트')) userAnswer['option']['리프트'] = lift; - if (optionKeys.includes('감마')) userAnswer['option']['감마'] = gamma; - if (optionKeys.includes('게인')) userAnswer['option']['게인'] = gain; - } - else if (name === '세피아') { - const u = xpath.select1('U/@value', effectData)?.value; - const v = xpath.select1('V/@value', effectData)?.value; + userAnswer = { + startColor: startColor, + endColor: endColor, + } - const optionKeys = Object.keys(rightAnswer['option']).map(key => key.toUpperCase()); - if (optionKeys.includes('U')) userAnswer['option']['U'] = u; - if (optionKeys.includes('V')) userAnswer['option']['V'] = v; - } - else if (name === '생동감') { - const vibranceValue = xpath.select1('VibranceValue/@value', effectData)?.value; - // 생동감 옵션값이 프로그램에서 적용한 값에 오차가 발생하는 경우가 있음 - // 곰픽>XML / 30>29 / 40>39 - // 설정한 값 그대로 적용되는 경우도 있어서 오차범위 2로 설정 - const userValue = parseInt(vibranceValue, 10); - const rightValue = parseInt(rightAnswer.option['생동감'], 10); + // JSON파일에서 대문자로 입력된 경우 소문자로 변환 + normalizedAnswer = { + startColor: rightAnswer.startColor.toLowerCase(), + endColor: rightAnswer.endColor.toLowerCase(), + } - if (Math.abs(rightValue - userValue) <= 2) { - const optionKeys = Object.keys(rightAnswer['option']); - if (optionKeys.includes('생동감')) { - userAnswer['option']['생동감'] = rightValue.toString(); + // 하나라도 일치하면 정답 + if (JSON.stringify(userAnswer) == JSON.stringify(normalizedAnswer)) { + isMatched = true; + break; + } + } + + // else { + else if (type.includes('shape') || type.includes('text') || type.includes('clipping')) { + const color = parseColorToHex(item.value); + userAnswer = color; + normalizedAnswer = rightAnswer.toLowerCase?.(); + + // 하나라도 일치하면 정답 + if (userAnswer === normalizedAnswer) { + isMatched = true; + break; } } } + totalScore += compareAndScore(userAnswer, normalizedAnswer, point, key, scoringResult); + } - for (const key in rightAnswer.option) { - // 속성값이 정답과 다른 경우가 있으면 오답처리 - if (rightAnswer.option[key] !== userAnswer.option[key]) { - isMatched = false; + else if (type === 'layer.blend.opacity') { + const layers = xpath.select(ele, gpdpXmlDoc); + let isMatched = false; + + for (const layer of layers) { + const blendop = xpath.select1('BlendOp/@value', layer).value; + const opacity = xpath.select1('Opacity/@value', layer).value; + + userAnswer = { + BlendOp: blendop, + Opacity: opacity, + } + + // 하나라도 일치하면 정답 + if (JSON.stringify(userAnswer) == JSON.stringify(rightAnswer)) { + isMatched = true; break; } + } + + totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); + continue; + } + + // [5-20] + else if (type === 'shadow') { + const shapes = xpath.select(ele, gpdpXmlDoc); + + for (const shape of shapes) { + // 그림자 설정 여부 + const shadowExists = xpath.select1('contains(draw_type/@value, "Shadow")', shape); + // Shadow 옵션이 있다면 + if (shadowExists) { + // 두께 + const width = xpath.select1('shadow_width/@value', shape).value; + // 거리 + const distance = xpath.select1('shadow_distance/@value', shape).value; + // 분산도 + const blur = xpath.select1('shadow_blur/@value', shape).value; + // 각도 + const angle = xpath.select1('shadow_angle/@value', shape).value; + + userAnswer = { + shadow: shadowExists, + width: width, + distance: distance, + blur: blur, + angle: angle, + } + } else { - isMatched = true; + userAnswer = { + shadow: shadowExists, + width: null, + distance: null, + blur: null, + angle: null, + } + } } - - // 속성값이 하나라도 일치하지 않으면 오답 - if (isMatched === false) { - break; - } + // console.log("🚀 ~ userAnswer:", userAnswer); + // console.log("🚀 ~ rightAnswer : ", rightAnswer) + totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult, { + partial: true + }) + continue; } - totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); - continue; - } - // - else if (type === "exists") { - const existsValues = xpath.select(ele, gpdpXmlDoc); - let isMatched = false; + else if (type == "boolean") { + const items = xpath.select(ele, gpdpXmlDoc); - for (const v of existsValues) { - // 하나라도 일치하면 정답 - if (v.value === rightAnswer) { - userAnswer = v.value; - isMatched = true; - break; + // xpath 결과값을 반환하는 요소가 없을 경우 + if (!items) { + scoringResult[key] = 0; + console.log("❌ 찾는 요소 없음"); } - } - // if (isMatched) { - - // } - // else { - - // } - totalScore = compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); - } - - - // else if (type === "shape.size") { - else if (type.includes("size")) { - const items = xpath.select(ele, gpdpXmlDoc); - let isMatched = false; - - // 각 Item 요소별 x,y 좌표 시작점과 끝점의 거리를 계산해 정답과 비교 - for (const item of items) { - const x1 = Number(xpath.select1('Item[1]/X/@value', item)?.value); - const y1 = Number(xpath.select1('Item[1]/Y/@value', item)?.value); - - const x2 = Number(xpath.select1('Item[last()]/X/@value', item)?.value); - const y2 = Number(xpath.select1('Item[last()]/Y/@value', item)?.value); - - const width = Math.round(Math.abs(x2 - x1)); - const height = Math.round(Math.abs(y2 - y1)); - - userAnswer = { - width: width, - height: height, - }; - - // 하나라도 일치하면 정답 - if (JSON.stringify(userAnswer) == JSON.stringify(rightAnswer)) { - isMatched = true; - break; + else { + totalScore += point; + scoringResult[key] = point; + console.log("✅ 찾는 요소 존재함"); } } - totalScore = compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); - continue; - } + // 이펙트 효과의 이름과 속성값을 비교 + else if (type == "effects") { + const items = xpath.select(ele, gpdpXmlDoc); + let matched = false; - // [1-8] - else if (type.includes("color")) { - const items = xpath.select(ele, gpdpXmlDoc); - let normalizedAnswer = null; - let isMatched = false; + // 각 Item 요소별 이름과 속성값을 구하고 정답과 비교 + for (const item of items) { + const name = xpath.select1('Name/@value', item)?.value; + const attr = xpath.select1(`EffectData/${option?.replace(/"/g, '')}/@value`, item)?.value; - for (const item of items) { - if (type.includes('gradient')) { - const startColorXpath = scoringData[key].startColor; - const endColorXpath = scoringData[key].endColor; - - const startColorRGB = xpath.select1(startColorXpath, item).value; - const endColorRGB = xpath.select1(endColorXpath, item).value; - - const startColor = parseColorToHex(startColorRGB); - const endColor = parseColorToHex(endColorRGB); - - userAnswer = { - startColor: startColor, - endColor: endColor, - } - - // JSON파일에서 대문자로 입력된 경우 소문자로 변환 - normalizedAnswer = { - startColor: rightAnswer.startColor.toLowerCase(), - endColor: rightAnswer.endColor.toLowerCase(), - } - - // 하나라도 일치하면 정답 - if (JSON.stringify(userAnswer) == JSON.stringify(normalizedAnswer)) { - isMatched = true; + if (name === rightAnswer[0] && attr === rightAnswer[1]) { + totalScore += point; + scoringResult[key] = point; + matched = true; + console.log("✅ 정답 일치:", rightAnswer); break; } } - // else if (type.includes('shape') || type.includes('text') || type.includes('clipping')) { - else { - const color = parseColorToHex(item.value); - userAnswer = color; - normalizedAnswer = rightAnswer.toLowerCase?.(); + if (!matched) { + scoringResult[key] = 0; + console.log("❌ 정답 없음:", rightAnswer); + } + } - // 하나라도 일치하면 정답 - if (userAnswer === normalizedAnswer) { - isMatched = true; - break; + else if (type == "multiValue") { + if (Array.isArray(rightAnswer)) { + const result = ele ? xpath.select(ele, gpdpXmlDoc) : []; + const resultValues = Array.isArray(result) ? result.map(r => (typeof r === 'object' ? r.value : r)) : [result]; + console.log("🚀 ~ getGpdpScore ~ resultValues:", resultValues) + + const groupSize = rightAnswer.length; + const groupedResult = []; + for (let i = 0; i < resultValues.length; i += groupSize) { + groupedResult.push(resultValues.slice(i, i + groupSize)); + } + console.log("🚀 ~ getGpdpScore ~ groupedResult:", groupedResult) + + // 배열 비교 함수 + function arraysEqual(arr1, arr2) { + if (arr1.length !== arr2.length) return false; + return arr1.every((value, index) => value === arr2[index]); + } + + // groupedResult 내부 배열에서 rightAnswer와 일치하는 배열이 있는지 확인 + const isMatch = groupedResult.some(group => arraysEqual(group, rightAnswer)); + + if (isMatch) { + totalScore += point; + scoringResult[key] = point; + console.log("🚀 ~ 정답 포함"); + } else { + scoringResult[key] = 0; + console.log("🚀 ~ 오답"); } } } - totalScore = compareAndScore(userAnswer, normalizedAnswer, point, key, scoringResult); - } - else if (type === 'layer.blend.opacity') { - const layers = xpath.select(ele, gpdpXmlDoc); - let isMatched = false; - - for (const layer of layers) { - const blendop = xpath.select1('BlendOp/@value', layer).value; - const opacity = xpath.select1('Opacity/@value', layer).value; - - userAnswer = { - BlendOp: blendop, - Opacity: opacity, + else if (type == "exact") { + let result = xpath.select(ele, gpdpXmlDoc); + if (result.length == 0) { + scoringResult[key] = 0; + console.log('ele not found'); + continue; } - - // 하나라도 일치하면 정답 - if (JSON.stringify(userAnswer) == JSON.stringify(rightAnswer)) { - isMatched = true; - break; - } - } - - totalScore = compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); - continue; - } - - // [5-20] - else if (type === 'shadow') { - const shapes = xpath.select(ele, gpdpXmlDoc); - - for (const shape of shapes) { - // 그림자 설정 여부 - const shadowExists = xpath.select1('contains(draw_type/@value, "Shadow")', shape); - // Shadow 옵션이 있다면 - if (shadowExists) { - // 두께 - const width = xpath.select1('shadow_width/@value', shape).value; - // 거리 - const distance = xpath.select1('shadow_distance/@value', shape).value; - // 분산도 - const blur = xpath.select1('shadow_blur/@value', shape).value; - // 각도 - const angle = xpath.select1('shadow_angle/@value', shape).value; - - userAnswer = { - shadow: shadowExists, - width: width, - distance: distance, - blur: blur, - angle: angle, - } - } - else { - userAnswer = { - shadow: shadowExists, - width: null, - distance: null, - blur: null, - angle: null, - } - - } - } - console.log("🚀 ~ userAnswer:", userAnswer); - console.log("🚀 ~ rightAnswer : ", rightAnswer) - totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult, { - partial: true - }) - continue; - } - - else if (type == "boolean") { - const items = xpath.select(ele, gpdpXmlDoc); - - // xpath 결과값을 반환하는 요소가 없을 경우 - if (!items) { - scoringResult[key] = 0; - console.log("❌ 찾는 요소 없음"); - } - else { - totalScore += point; - scoringResult[key] = point; - console.log("✅ 찾는 요소 존재함"); - } - } - - // 이펙트 효과의 이름과 속성값을 비교 - else if (type == "effects") { - const items = xpath.select(ele, gpdpXmlDoc); - let matched = false; - - // 각 Item 요소별 이름과 속성값을 구하고 정답과 비교 - for (const item of items) { - const name = xpath.select1('Name/@value', item)?.value; - const attr = xpath.select1(`EffectData/${option?.replace(/"/g, '')}/@value`, item)?.value; - - if (name === rightAnswer[0] && attr === rightAnswer[1]) { + if (result[0].value === rightAnswer) { totalScore += point; scoringResult[key] = point; - matched = true; - console.log("✅ 정답 일치:", rightAnswer); - break; - } - } - - if (!matched) { - scoringResult[key] = 0; - console.log("❌ 정답 없음:", rightAnswer); - } - } - - else if (type == "multiValue") { - if (Array.isArray(rightAnswer)) { - const result = ele ? xpath.select(ele, gpdpXmlDoc) : []; - const resultValues = Array.isArray(result) ? result.map(r => (typeof r === 'object' ? r.value : r)) : [result]; - console.log("🚀 ~ getGpdpScore ~ resultValues:", resultValues) - - const groupSize = rightAnswer.length; - const groupedResult = []; - for (let i = 0; i < resultValues.length; i += groupSize) { - groupedResult.push(resultValues.slice(i, i + groupSize)); - } - console.log("🚀 ~ getGpdpScore ~ groupedResult:", groupedResult) - - // 배열 비교 함수 - function arraysEqual(arr1, arr2) { - if (arr1.length !== arr2.length) return false; - return arr1.every((value, index) => value === arr2[index]); - } - - // groupedResult 내부 배열에서 rightAnswer와 일치하는 배열이 있는지 확인 - const isMatch = groupedResult.some(group => arraysEqual(group, rightAnswer)); - - if (isMatch) { - totalScore += point; - scoringResult[key] = point; - console.log("🚀 ~ 정답 포함"); } else { scoringResult[key] = 0; - console.log("🚀 ~ 오답"); + console.log('ele not matched, ' + result[0].value); } } - } - else if (type == "exact") { - let result = xpath.select(ele, gpdpXmlDoc); - if (result.length == 0) { - scoringResult[key] = 0; - console.log('ele not found'); - continue; + + else if (type == "multi") { + try { + const result = xpath.select(ele, gpdpXmlDoc); + let isSame = true; + // console.log(`ele: ${ele}, value: ${value} result: ${result}`); + + if (result.length == 0) { + console.log('result length 0'); + scoringResult[key] = 0; + continue; + } + + result.forEach((v, i) => { + // value[i] 값이 정수형인 경우에는 float로 변환하여 비교 + // 정수형 v값을 float 형으로 변환하고 소수점 3자리까지 버림 + let temp = v.value; + let answer = rightAnswer[i]; + + if (Number.isFinite(rightAnswer[i]) && !Number.isInteger(rightAnswer[i])) { + temp = parseFloat(v.value); + answer = parseFloat(rightAnswer[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; + scoringResult[key] = isSame ? point : 0; + } catch (e) { + console.log('err :', e); + scoringResult[key] = 0; + } } - if (result[0].value === rightAnswer) { - totalScore += point; - scoringResult[key] = point; - } else { - scoringResult[key] = 0; - console.log('ele not matched, ' + result[0].value); + else if (type == "gradient") { + const items = xpath.select(ele, gpdpXmlDoc); + const startColorXpath = scoringData[key].startColor; + const endColorXpath = scoringData[key].endColor; + let matched = false; + + for (const item of items) { + const startColor = parseColorToHex(xpath.select1(startColorXpath, item)?.value); + const endColor = parseColorToHex(xpath.select1(endColorXpath, item)?.value); + + console.log(startColor + ":" + rightAnswer["startColor"], endColor + ":" + rightAnswer["endColor"]); + + if (startColor === rightAnswer["startColor"] && endColor === rightAnswer["endColor"]) { + totalScore += point; + scoringResult[key] = point; + matched = true; + console.log("✅ 정답 일치:", rightAnswer); + break; + } + } + if (!matched) { + scoringResult[key] = 0; + console.log("❌ 정답 없음:", rightAnswer); + } } - } + // 그림자 속성이 있는지 여부 파악해서 그림자 속성 별로 점수 1 점씩 부여 + else if (type == "shadow") { + const result = xpath.select(ele["shadow"], gpdpXmlDoc); + let shadowScore = 0; + if (result.length == 0) { + scoringResult[key] = 0; + console.log('shadow not found'); + continue; + } - else if (type == "multi") { - try { + shadowScore += 1; + const width = xpath.select(ele["width"], gpdpXmlDoc); + const distance = xpath.select(ele["distance"], gpdpXmlDoc); + const blur = xpath.select(ele["blur"], gpdpXmlDoc); + const angle = xpath.select(ele["angle"], gpdpXmlDoc); + + if (width.length !== 0 && width[0].value == rightAnswer["width"]) { + shadowScore += 1; + console.log('width matched'); + } + if (distance.length !== 0 && distance[0].value == rightAnswer["distance"]) { + shadowScore += 1; + console.log('distance matched'); + } + if (blur.length !== 0 && blur[0].value == rightAnswer["blur"]) { + shadowScore += 1; + console.log('blur matched'); + } + if (angle.length !== 0 && angle[0].value == rightAnswer["angle"]) { + shadowScore += 1; + console.log('angle matched'); + } + totalScore += shadowScore; + scoringResult[key] = shadowScore; + } + else { const result = xpath.select(ele, gpdpXmlDoc); - let isSame = true; - // console.log(`ele: ${ele}, value: ${value} result: ${result}`); + const result2 = null; + let isCheck = false; if (result.length == 0) { - console.log('result length 0'); - scoringResult[key] = 0; - continue; + isCheck = true; } + if (isCheck && ele2) { + result2 = xpath.select(ele2, gpdpXmlDoc); - result.forEach((v, i) => { - // value[i] 값이 정수형인 경우에는 float로 변환하여 비교 - // 정수형 v값을 float 형으로 변환하고 소수점 3자리까지 버림 - let temp = v.value; - let answer = rightAnswer[i]; - - if (Number.isFinite(rightAnswer[i]) && !Number.isInteger(rightAnswer[i])) { - temp = parseFloat(v.value); - answer = parseFloat(rightAnswer[i]); - // 소수점 3자리까지 버림 - temp = Math.floor(temp * 1000) / 1000; + if (result2.length == 0) { + scoringResult[key] = 0; + continue; } - // 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; - scoringResult[key] = isSame ? point : 0; - } catch (e) { - console.log('err :', e); - scoringResult[key] = 0; - } - } - else if (type == "gradient") { - const items = xpath.select(ele, gpdpXmlDoc); - const startColorXpath = scoringData[key].startColor; - const endColorXpath = scoringData[key].endColor; - let matched = false; - - for (const item of items) { - const startColor = parseColorToHex(xpath.select1(startColorXpath, item)?.value); - const endColor = parseColorToHex(xpath.select1(endColorXpath, item)?.value); - - console.log(startColor + ":" + rightAnswer["startColor"], endColor + ":" + rightAnswer["endColor"]); - - if (startColor === rightAnswer["startColor"] && endColor === rightAnswer["endColor"]) { - totalScore += point; - scoringResult[key] = point; - matched = true; - console.log("✅ 정답 일치:", rightAnswer); - break; + result = result2; + // console.log(`1st isChecked: ${isCheck}, result: ${result}`) } - } - if (!matched) { - scoringResult[key] = 0; - console.log("❌ 정답 없음:", rightAnswer); + // value와 result[0].value를 비교하여 같으면 점수 point 부여 + // console.log(`${(value === result[0].value)}, ${result.length > 0 && value === result[0].value} `) + // console.log(`2nd isChecked: ${isCheck}, result: ${result}`) + totalScore += result.length > 0 ? point : 0; + scoringResult[key] = result.length > 0 ? point : 0; } } - // 그림자 속성이 있는지 여부 파악해서 그림자 속성 별로 점수 1 점씩 부여 - else if (type == "shadow") { - - const result = xpath.select(ele["shadow"], gpdpXmlDoc); - let shadowScore = 0; - if (result.length == 0) { - scoringResult[key] = 0; - console.log('shadow not found'); - continue; - } - - shadowScore += 1; - const width = xpath.select(ele["width"], gpdpXmlDoc); - const distance = xpath.select(ele["distance"], gpdpXmlDoc); - const blur = xpath.select(ele["blur"], gpdpXmlDoc); - const angle = xpath.select(ele["angle"], gpdpXmlDoc); - - if (width.length !== 0 && width[0].value == rightAnswer["width"]) { - shadowScore += 1; - console.log('width matched'); - } - if (distance.length !== 0 && distance[0].value == rightAnswer["distance"]) { - shadowScore += 1; - console.log('distance matched'); - } - if (blur.length !== 0 && blur[0].value == rightAnswer["blur"]) { - shadowScore += 1; - console.log('blur matched'); - } - if (angle.length !== 0 && angle[0].value == rightAnswer["angle"]) { - shadowScore += 1; - console.log('angle matched'); - } - totalScore += shadowScore; - scoringResult[key] = shadowScore; - } - else { - const result = xpath.select(ele, gpdpXmlDoc); - const result2 = null; - let isCheck = false; - - if (result.length == 0) { - isCheck = true; - } - if (isCheck && ele2) { - result2 = xpath.select(ele2, gpdpXmlDoc); - - if (result2.length == 0) { - scoringResult[key] = 0; - continue; - } - result = result2; - // console.log(`1st isChecked: ${isCheck}, result: ${result}`) - } - // value와 result[0].value를 비교하여 같으면 점수 point 부여 - // console.log(`${(value === result[0].value)}, ${result.length > 0 && value === result[0].value} `) - // console.log(`2nd isChecked: ${isCheck}, result: ${result}`) - totalScore += result.length > 0 ? point : 0; - scoringResult[key] = result.length > 0 ? point : 0; - } -} -scoringResult['총점'] = totalScore; -return scoringResult; + scoringResult['총점'] = totalScore; + return scoringResult; } diff --git a/psdExport_2.js b/psdExport_2.js index d4660d8..bd79421 100644 --- a/psdExport_2.js +++ b/psdExport_2.js @@ -24,8 +24,8 @@ const examTypes = [ ]; // testMode가 true일 경우 TEST 폴더에 있는 답안 파일을 읽어옴 -const testMode = false; -// const testMode = true; +// const testMode = false; +const testMode = true; const outputExcelFiles = []; @@ -459,7 +459,7 @@ function getGmepScore(gmepData, scoringJson, index) { // 만약 CRClip 요소가 motion clip인 경우 CRCUnitArr의 Path를 찾기 if (mediaPath == null) { const motionClipPath = xpath.select1(`//CRClipArr/CRClip[${CRClipIndex}]/CRCUnitArr/@Path`, gmepXmlDoc); - if (motionClipPath !== null) { + if (motionClipPath != null) { const fileName = path.basename(motionClipPath.value); mediaOrderList.push(fileName); } @@ -616,7 +616,7 @@ function getGmepScore(gmepData, scoringJson, index) { else { const xpathExpr = ele?.replace(/{CRClipIndex}/g, crclipIndex); const muteStatus = xpath.select1(xpathExpr, gmepXmlDoc); - userAnswer = muteStatus.value; + userAnswer = muteStatus?.value; } totalScore += compareAndScore(userAnswer, rightAnswer, point, key, scoringResult); } @@ -649,7 +649,7 @@ function getGmepScore(gmepData, scoringJson, index) { if (!crTrackClip) { userAnswer = null; } else { - const length = parseInt(crTrackClip.getAttribute('Length'), 10); + const length = crTrackClip.getAttribute('Length'); userAnswer = length; } }