From 99250cd161d56790fdf4fd39bde063e5c6be873c Mon Sep 17 00:00:00 2001 From: dragdra Date: Wed, 1 Oct 2025 17:32:30 +0900 Subject: [PATCH] =?UTF-8?q?2509=ED=9A=8C=20=EC=B1=84=EC=A0=90=EC=9E=90?= =?UTF-8?q?=EB=A3=8C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 01_copyFiles.py | 4 +- 02_extract_project_json.py | 4 +- 251001_2509_CAT_3_A_채점결과.xlsx | Bin 0 -> 5210 bytes __pycache__/script_utils.cpython-312.pyc | Bin 3716 -> 3745 bytes correct/2509_CAT_3_A.json | 557 +++++++++++++++++++++++ logs/cat.log | 8 + main.py | 6 +- script_utils.py | 2 +- 시험자료/2507/2507_CAT_3_A.json | 362 +++++++++++++++ 9 files changed, 935 insertions(+), 8 deletions(-) create mode 100644 251001_2509_CAT_3_A_채점결과.xlsx create mode 100644 correct/2509_CAT_3_A.json create mode 100644 시험자료/2507/2507_CAT_3_A.json diff --git a/01_copyFiles.py b/01_copyFiles.py index 7eeae4a..5cfff00 100644 --- a/01_copyFiles.py +++ b/01_copyFiles.py @@ -47,8 +47,8 @@ def copy_ent_files(source_root, target_root): # 사용법 -source_directory = r"D:\project\data\CAS_제2508회 정기\답안파일\(전체답안)1교시2교시나눔\B형" # 원본 디렉토리 경로 -target_directory = r".\ent\2508_CAS_2_B" +source_directory = r"D:\project\Entry\Entry-Scoring\시험자료\2509\A" # 원본 디렉토리 경로 +target_directory = r".\ent\2509_CAT_3_A" # target_directory_a = r"./output/A" # '1교시'의 타겟 경로 # target_directory_b = r"./output/B" # '2교시'의 타겟 경로 # target_directory_c = r"./output/C" # '3교시'의 타겟 경로 diff --git a/02_extract_project_json.py b/02_extract_project_json.py index 0c1223d..201daef 100644 --- a/02_extract_project_json.py +++ b/02_extract_project_json.py @@ -50,8 +50,8 @@ def process_ent_files(ent_dir, output_dir): # 실행 예 if __name__ == "__main__": - # test_names = ["2507_CAT_3_A"] - test_names = ["2508_CAS_2_A","2508_CAS_2_B"] + test_names = ["2509_CAT_3_A"] + # test_names = ["2508_CAS_2_A","2508_CAS_2_B"] for test_name in test_names: ent_dir = f".\\ent\\{test_name}" output_dir = f".\\output\\{test_name}" diff --git a/251001_2509_CAT_3_A_채점결과.xlsx b/251001_2509_CAT_3_A_채점결과.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..02d93074540cba1e26154fd02974aab3550e36a2 GIT binary patch literal 5210 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 AjQ{`u literal 0 HcmV?d00001 diff --git a/__pycache__/script_utils.cpython-312.pyc b/__pycache__/script_utils.cpython-312.pyc index db8f8e98c42cb75ab093bd14aa13594122855463..95cc78c26062ecfead6c5611317b47f51a180db7 100644 GIT binary patch delta 59 zcmZpXT`0?YnwOW00SIb3ZfE#zXf*i;o4jy-X-Pq8NsN)Hfn~h2V{p82yyN7n OJj)neHrMcSFaiJ>;u1>$ delta 56 zcmZ1|+ak+*nwOW00SL7CHe^_CcUs_U7S`uSqYG4uX>=+zx6z??o6VEb6 K_02PRIT!)2J`fuK diff --git a/correct/2509_CAT_3_A.json b/correct/2509_CAT_3_A.json new file mode 100644 index 0000000..bcde020 --- /dev/null +++ b/correct/2509_CAT_3_A.json @@ -0,0 +1,557 @@ +{ + "1-1": { + "type": "scene", + "ele": "$..objects[?(@.name=='화산')]", + "points": 2, + "desc": "문제 1/화산섬/[배경] 이름 설정/이름을 '화산'으로 변경하기", + "sort": 11 + }, + "1-3": { + "type": "scene", + "ele": "$..objects[?(@.name=='불')]", + "points": 2, + "desc": "문제 1/불(2)/[개체] 이름 설정 1/이름을 '불'로 변경하기", + "sort": 13 + }, + "1-4": { + "type": "scene", + "ele": "$..objects[?(@.name=='공룡')]", + "points": 2, + "desc": "문제 1/공룡/[개체] 이름 설정 2/이름 변경 없음", + "sort": 14 + }, + "1-5": { + "type": "scene", + "ele": "$..objects[?(@.name=='알')]", + "points": 2, + "desc": "문제 1/계란/[개체] 이름 설정 3/이름을 '알'로 변경하기", + "sort": 15 + }, + "1-6": { + "type": "scene", + "ele": "$..objects[?(@.name=='바위')]", + "points": 2, + "desc": "문제 1/바위(4)/[개체] 이름 설정 4/이름을 '바위'로 변경하기", + "sort": 16 + }, + "2-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'불')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.14, + "desc": "문제 2/불/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": [ + "$[0][1].type", + "$[0][1].params[0].params[0]", + "$[0][1].params[1].params[0]" + ], + "answer": [ + "locate_xy", + "120", + "90" + ], + "points": 2.14, + "desc": "문제 2/불/[시작]의 세부 동작 1/x: '120' y: '90' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][2].params[0].params[0]", + "answer": "130", + "points": 2.14, + "desc": "문제 2/불/[시작]의 세부 동작 2/크기를 '130' 으로 정하기" + }, + { + "ele": [ + "$[0][3].type", + "$[0][3].params[0]" + ], + "answer": [ + "repeat_inf", + null + ], + "points": 2.14, + "desc": "문제 2/불/반복/계속 반복하기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][0].type", + "$[0][3].statements[0][0].params[0].type" + ], + "answer": [ + "change_to_some_shape", + "get_pictures" + ], + "points": 2.14, + "desc": "문제 2/불/[반복]의 세부 동작 1/'불(2)_3' 모양으로 바꾸기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][1].type", + "$[0][3].statements[0][1].params[0].params[0]" + ], + "answer": [ + "wait_second", + "0.5" + ], + "points": 2.14, + "desc": "문제 2/불/[반복]의 세부 동작 2/'0.5' 초 기다리기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][2].type", + "$[0][3].statements[0][2].params[0].type" + ], + "answer": [ + "change_to_some_shape", + "get_pictures" + ], + "points": 2.14, + "desc": "문제 2/불/[반복]의 세부 동작 3/'불(2)_1' 모양으로 바꾸기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][3].type", + "$[0][3].statements[0][3].params[0].params[0]" + ], + "answer": [ + "wait_second", + "0.5" + ], + "points": 2.14, + "desc": "문제 2/불/[반복]의 세부 동작 4/'0.5' 초 기다리기", + "type": "list" + } + ], + "sort": 102 + }, + "3-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'공룡')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.14, + "desc": "문제 2/공룡/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": [ + "$[0][1].type", + "$[0][1].params[0].params[0]", + "$[0][1].params[1].params[0]" + ], + "answer": [ + "locate_xy", + "0", + "-20" + ], + "points": 2.14, + "desc": "문제 2/공룡/[시작]의 세부 동작 1/x: '0' y: '-20' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][2].params[*].params", + "answer": [ + "공룡알을 구하자", + "1" + ], + "points": 2.14, + "desc": "문제 2/공룡/[시작]의 세부 동작 2/'공룡알을 구하자' 를 '1' 초 동안 '말하기'" + }, + { + "ele": [ + "$[0][3].type", + "$[0][3].params[0]" + ], + "answer": [ + "repeat_inf", + null + ], + "points": 2.14, + "desc": "문제 2/공룡/반복/계속 반복하기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][0].type", + "$[0][3].statements[0][0].params[0].type", + "$[0][3].statements[0][0].params[0].params[0]" + ], + "answer": [ + "_if", + "is_press_some_key", + "38" + ], + "points": 2.14, + "desc": "문제 2/공룡/만일 1/만일 '위쪽 화살표' 키가 눌러져 있는가? 라면", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][0].statements[0][0].type", + "$[0][3].statements[0][0].statements[0][0].params[0].params[0]" + ], + "answer": [ + "move_y", + "5" + ], + "points": 2.14, + "desc": "문제 2/공룡/[만일 1]의 세부 동작/y 좌표를 '5' 만큼 바꾸기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][1].type", + "$[0][3].statements[0][1].params[0].type", + "$[0][3].statements[0][1].params[0].params[0]" + ], + "answer": [ + "_if", + "is_press_some_key", + "40" + ], + "points": 2.14, + "desc": "문제 2/공룡/만일 2/만일 '아래쪽 화살표' 키가 눌러져 있는가? 라면", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][1].statements[0][0].type", + "$[0][3].statements[0][1].statements[0][0].params[0].params[0]" + ], + "answer": [ + "move_y", + "-5" + ], + "points": 2.14, + "desc": "문제 2/공룡/[만일 2]의 세부 동작/y 좌표를 '-5' 만큼 바꾸기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][2].type", + "$[0][3].statements[0][2].params[0].type", + "$[0][3].statements[0][2].params[0].params[0]" + ], + "answer": [ + "_if", + "is_press_some_key", + "37" + ], + "points": 2.14, + "desc": "문제 2/공룡/만일 3/만일 '왼쪽 화살표' 키가 눌러져 있는가? 라면", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][2].statements[0][0].type", + "$[0][3].statements[0][2].statements[0][0].params[0].params[0]" + ], + "answer": [ + "move_x", + "-5" + ], + "points": 2.14, + "desc": "문제 2/공룡/[만일 3]의 세부 동작/x 좌표를 '-5' 만큼 바꾸기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][3].type", + "$[0][3].statements[0][3].params[0].type", + "$[0][3].statements[0][3].params[0].params[0]" + ], + "answer": [ + "_if", + "is_press_some_key", + "39" + ], + "points": 2.14, + "desc": "문제 2/공룡/만일 4/만일 '오른쪽 화살표' 키가 눌러져 있는가? 라면", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][3].statements[0][0].type", + "$[0][3].statements[0][3].statements[0][0].params[0].params[0]" + ], + "answer": [ + "move_x", + "5" + ], + "points": 2.14, + "desc": "문제 2/공룡/[만일 4]의 세부 동작/x 좌표를 '5' 만큼 바꾸기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][4].type", + "$[0][3].statements[0][4].params[0].type" + ], + "answer": [ + "_if", + "reach_something" + ], + "points": 2.14, + "desc": "문제 2/공룡/만일 5/만일 '불' 에 닿았는가? 라면", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][4].statements[0][0].type", + "$[0][3].statements[0][4].statements[0][0].params[0].params[0]", + "$[0][3].statements[0][4].statements[0][0].params[1]" + ], + "answer": [ + "dialog", + "앗 뜨거워!", + "speak" + ], + "points": 2.14, + "desc": "문제 2/공룡/[만일 5]의 세부 동작 1/'앗 뜨거워!' 를 '말하기'", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][4].statements[0][1].type", + "$[0][3].statements[0][4].statements[0][1].params[0].params[0]" + ], + "answer": [ + "wait_second", + "1" + ], + "points": 2.14, + "desc": "문제 2/공룡/[만일 5]의 세부 동작 2/'1' 초 기다리기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][4].statements[0][2].type", + "$[0][3].statements[0][4].statements[0][2].params[0]" + ], + "answer": [ + "stop_object", + "all" + ], + "points": 2.14, + "desc": "문제 2/공룡/[만일 5]의 세부 동작 3/'모든' 코드 멈추기", + "type": "list" + } + ], + "sort": 110 + }, + "4-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'알|계')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.14, + "desc": "문제 2/알/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": "$[0][1].params[0].params[0]", + "answer": "50", + "points": 2.14, + "desc": "문제 2/알/[시작]의 세부 동작 1/크기를 '50' 으로 정하기" + }, + { + "ele": [ + "$[0][2].type", + "$[0][2].params[0].params[0]" + ], + "answer": [ + "rotate_absolute", + "270" + ], + "points": 2.14, + "desc": "문제 2/알/[시작]의 세부 동작 2/방향을 '270°' 로 정하기", + "type": "list" + }, + { + "ele": [ + "$[0][3].type", + "$[0][3].params[0]" + ], + "answer": [ + "repeat_inf", + null + ], + "points": 2.14, + "desc": "문제 2/알/반복/계속 반복하기", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][0].type", + "answer": "show", + "points": 2.14, + "desc": "문제 2/알/[반복]의 세부 동작 1/모양 보이기" + }, + { + "ele": [ + "$[0][3].statements[0][1].type", + "$[0][3].statements[0][1].params[0].params[1].params[0]", + "$[0][3].statements[0][1].params[0].params[3].params[0]", + "$[0][3].statements[0][1].params[1].params[1].params[0]", + "$[0][3].statements[0][1].params[1].params[3].params[0]" + ], + "answer": [ + "locate_xy", + "55", + "160", + "5", + "10" + ], + "points": 2.2, + "desc": "문제 2/알/[반복]의 세부 동작 2/x: '55 부터 160 사이의 무작위 수' y: '5 부터 10 사이의 무작위 수' 위치로 이동하기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][2].type", + "$[0][3].statements[0][2].params[0].params[0]", + "$[0][3].statements[0][2].params[1].params[1].params[0]", + "$[0][3].statements[0][2].params[1].params[3].params[0]", + "$[0][3].statements[0][2].params[2].params[0]" + ], + "answer": [ + "move_xy_time", + "2", + "-200", + "200", + "-140" + ], + "points": 2.2, + "desc": "문제 2/알/[반복]의 세부 동작 3/'2' 초 동안 x: '-200 부터 200 사이의 무작위 수' y: '-140' 만큼 움직이기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][3].type", + "$[0][3].statements[0][3].params[0].type" + ], + "answer": [ + "_if", + "reach_something" + ], + "points": 2.14, + "desc": "문제 2/알/만일/만일 '바위' 에 닿았는가? 라면", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][3].statements[0][0].params[*].params", + "answer": [ + "공룡알이 깨졌다!", + "0.2" + ], + "points": 2.14, + "desc": "문제 2/알/[만일]의 세부 동작 1/'공룡알이 깨졌다!' 를 '0.2' 초 동안 '말하기'" + }, + { + "ele": "$[0][3].statements[0][3].statements[0][1].type", + "answer": "hide", + "points": 2.14, + "desc": "문제 2/알/[만일]의 세부 동작 2/모양 숨기기" + }, + { + "ele": "$[1][0].params", + "answer": [ + null, + "32" + ], + "points": 2.14, + "desc": "문제 2/알/스페이스/'스페이스' 키를 눌렀을 때" + }, + { + "ele": [ + "$[1][1].type", + "$[1][1].params[0]" + ], + "answer": [ + "repeat_inf", + null + ], + "points": 2.14, + "desc": "문제 2/알/반복/계속 반복하기", + "type": "list" + }, + { + "ele": [ + "$[1][1].statements[0][0].type", + "$[1][1].statements[0][0].params[0].type" + ], + "answer": [ + "_if", + "reach_something" + ], + "points": 2.14, + "desc": "문제 2/알/만일/만일 '공룡' 에 닿았는가? 라면", + "type": "list" + }, + { + "ele": "$[1][1].statements[0][0].statements[0][0].type", + "answer": "locate", + "points": 2.14, + "desc": "문제 2/알/[만일]의 세부 동작 1/'공룡' 위치로 이동하기" + }, + { + "ele": [ + "$[1][1].statements[0][0].statements[0][1].type", + "$[1][1].statements[0][0].statements[0][1].params[0].params[0]" + ], + "answer": [ + "move_x", + "-20" + ], + "points": 2.14, + "desc": "문제 2/알/[만일]의 세부 동작 2/x 좌표를 '-20' 만큼 바꾸기", + "type": "list" + } + ], + "sort": 126 + }, + "5-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'바위')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.14, + "desc": "문제 2/바위/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": [ + "$[0][1].type", + "$[0][1].params[0].params[0]", + "$[0][1].params[1].params[0]" + ], + "answer": [ + "locate_xy", + "130", + "-120" + ], + "points": 2.14, + "desc": "문제 2/바위/[시작]의 세부 동작 1/x: '130' y: '-120' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][2].params[0].params[0]", + "answer": "150", + "points": 2.14, + "desc": "문제 2/바위/[시작]의 세부 동작 2/크기를 '150' 으로 정하기" + } + ], + "sort": 141 + } +} \ No newline at end of file diff --git a/logs/cat.log b/logs/cat.log index 66990b1..ba67d25 100644 --- a/logs/cat.log +++ b/logs/cat.log @@ -26,3 +26,11 @@ Traceback (most recent call last): File "D:\project\Entry\Entry-Scoring\main.py", line 162, in process_project total_points += question_points TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType' +[2025-10-01 15:43:18] [ERROR] [main:300] 🚫Error processing ./output/2509_CAT_3_A/2509_CAT_3_A\project.json: unsupported operand type(s) for +=: 'int' and 'NoneType' +Traceback (most recent call last): + File "D:\project\Entry\Entry-Scoring\main.py", line 295, in main + points = process_project(project_data, scoring_data) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "D:\project\Entry\Entry-Scoring\main.py", line 162, in process_project + total_points += question_points +TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType' diff --git a/main.py b/main.py index 6cd3afb..1564411 100644 --- a/main.py +++ b/main.py @@ -234,8 +234,8 @@ def main(): timestamp = datetime.now().strftime("%y%m%d") test_mode = False # 테스트 모드 설정 # test_mode = True # 테스트 모드 설정 - exam_round = "2508" - exam_names = ["CAS_2_A", "CAS_2_B"] # 여러 시험명을 리스트로 설정 + exam_round = "2509" + exam_names = ["CAT_3_A"] # 여러 시험명을 리스트로 설정 excel_list = [] for exam_name in exam_names: @@ -276,7 +276,7 @@ def main(): for file in sorted(files): # 파일도 정렬 if file == 'project.json': full_path = os.path.join(root, file) - print(f"\nProcessing: {full_path}") + print(f"\n🟠 Processing: {full_path}") try: # 디렉토리 패스 내에 학생 이름만 뽑아서 엑셀 컬럼 명으로 추가 match = re.search(r'(\d{6}[-_][^\\/]+)[\\/]', full_path) diff --git a/script_utils.py b/script_utils.py index fb772c2..5c4e2b8 100644 --- a/script_utils.py +++ b/script_utils.py @@ -60,7 +60,7 @@ def read_json(file_path): def main(): # base_dir을 코드 내에서 직접 지정 - base_dir = r".\output\2508_CAS_2_B" # 원하는 최상위 디렉토리 경로로 수정하세요 + base_dir = r"D:\project\Entry\Entry-Scoring\output\2509_CAS_3_A" # 원하는 최상위 디렉토리 경로로 수정 # 하위 디렉토리 순회 for root, dirs, files in os.walk(base_dir): diff --git a/시험자료/2507/2507_CAT_3_A.json b/시험자료/2507/2507_CAT_3_A.json new file mode 100644 index 0000000..5c8df3c --- /dev/null +++ b/시험자료/2507/2507_CAT_3_A.json @@ -0,0 +1,362 @@ +{ + "1-1": { + "type": "scene", + "ele": "$..objects[?(@.name=='실험실')]", + "points": 2, + "desc": "문제 1/교실 뒤(3)/[배경] 이름 설정/이름을 '실험실'으로 변경하기" + }, + "1-2": { + "type": "scene", + "ele": "$..objects[?(@.name=='새로운 약')]", + "points": 2, + "desc": "문제 1/물약(빨강)/[개체] 이름 설정 1/이름을 '새로운 약'으로 변경하기" + }, + "1-4": { + "type": "scene", + "ele": "$..objects[?(@.name=='불')]", + "points": 2, + "desc": "문제 1/불(2)/[개체] 이름 설정 2/이름을 '불'로 변경하기" + }, + "1-5": { + "type": "scene", + "ele": "$..objects[?(@.name=='마법사')]", + "points": 2, + "desc": "문제 1/꼬마 마법사/[개체] 이름 설정 3/이름을 '마법사'로 변경하기" + }, + "1-6": { + "type": "scene", + "ele": "$..objects[?(@.name=='마법의 약')]", + "points": 2, + "desc": "문제 1/마법의 약/[개체] 이름 설정 4/이름 변경 없음" + }, + "2-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'새로운 약|물약')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.43, + "desc": "문제 2/새로운 약/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": [ + "$[0][1].type", + "$[0][1].params[0].params[0]", + "$[0][1].params[1].params[0]" + ], + "answer": ["locate_xy", "50", "5"], + "points": 2.43, + "desc": "문제 2/새로운 약/[시작]의 세부 동작 1/x: '50' y: '5' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][2].params[0].params[0]", + "answer": "60", + "points": 2.43, + "desc": "문제 2/새로운 약/[시작]의 세부 동작 2/크기를 '60' 으로 정하기" + }, + { + "ele": "$[1][0].type", + "answer": "when_object_click", + "points": 2.43, + "desc": "문제 2/새로운 약/오브젝트/오브젝트를 클릭했을 때" + }, + { + "ele": ["$[1][1].type", "$[1][1].params[0]"], + "answer": ["repeat_inf", null], + "points": 2.43, + "desc": "문제 2/새로운 약/반복/계속 반복하기", + "type": "list" + }, + { + "ele": "$[1][1].statements[0][0].type", + "answer": "locate", + "points": 2.43, + "desc": "문제 2/새로운 약/[반복]의 세부 동작/'마우스 포인터' 위치로 이동하기" + } + ] + }, + "3-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'불')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.43, + "desc": "문제 2/불/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": [ + "$[0][1].type", + "$[0][1].params[0].params[0]", + "$[0][1].params[1].params[0]" + ], + "answer": ["locate_xy", "-150", "-30"], + "points": 2.43, + "desc": "문제 2/불/[시작]의 세부 동작 1/x: '-150' y: '-30' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][2].params[0].params[0]", + "answer": "90", + "points": 2.43, + "desc": "문제 2/불/[시작]의 세부 동작 2/크기를 '90' 으로 정하기" + }, + { + "ele": ["$[0][3].type", "$[0][3].params[0]"], + "answer": ["repeat_inf", null], + "points": 2.43, + "desc": "문제 2/불/반복/계속 반복하기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][0].type", + "$[0][3].statements[0][0].params[0].params[1].params[0]", + "$[0][3].statements[0][0].params[0].params[3].params[0]", + "$[0][3].statements[0][0].params[1].params[1].params[0]", + "$[0][3].statements[0][0].params[1].params[3].params[0]" + ], + "answer": ["locate_xy", "-150", "0", "-10", "40"], + "points": 2.43, + "desc": "문제 2/불/[반복]의 세부 동작 1/x: '-150 부터 0 사이의 무작위 수' y: '-10 부터 40 사이의 무작위 수' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][1].type", + "answer": "hide", + "points": 2.43, + "desc": "문제 2/불/[반복]의 세부 동작 2/모양 숨기기" + }, + { + "ele": [ + "$[0][3].statements[0][2].type", + "$[0][3].statements[0][2].params[0].type", + "$[0][3].statements[0][2].params[0].params[1].params[0]", + "$[0][3].statements[0][2].params[0].params[3].params[0]" + ], + "answer": ["wait_second", "calc_rand", "1", "2"], + "points": 2.43, + "desc": "문제 2/불/[반복]의 세부 동작 3/'1 부터 2 사이의 무작위 수' 초 기다리기", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][3].type", + "answer": "show", + "points": 2.43, + "desc": "문제 2/불/[반복]의 세부 동작 4/모양 보이기" + }, + { + "ele": [ + "$[0][3].statements[0][4].type", + "$[0][3].statements[0][4].params[0].params[0]" + ], + "answer": ["wait_second", "0.5"], + "points": 2.43, + "desc": "문제 2/불/[반복]의 세부 동작 5/'0.5' 초 기다리기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][5].type", + "$[0][3].statements[0][5].params[0].type" + ], + "answer": ["_if", "reach_something"], + "points": 2.43, + "desc": "문제 2/불/만일/만일 '새로운 약' 에 닿았는가? 라면", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][5].statements[0][0].params[0].params[0]", + "answer": "300", + "points": 2.43, + "desc": "문제 2/불/[만일]의 세부 동작 1/크기를 '300' 으로 정하기" + }, + { + "ele": [ + "$[0][3].statements[0][5].statements[0][1].type", + "$[0][3].statements[0][5].statements[0][1].params[0].params[0]", + "$[0][3].statements[0][5].statements[0][1].params[1]" + ], + "answer": ["dialog", "마법 실패", "speak"], + "points": 2.43, + "desc": "문제 2/불/[만일]의 세부 동작 2/'마법 실패' 를 '말하기'", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][5].statements[0][2].type", + "$[0][3].statements[0][5].statements[0][2].params[0]" + ], + "answer": ["stop_object", "all"], + "points": 2.43, + "desc": "문제 2/불/[만일]의 세부 동작 3/'모든' 코드 멈추기", + "type": "list" + } + ] + }, + "4-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'마법사')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.43, + "desc": "문제 2/마법사/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": [ + "$[0][1].type", + "$[0][1].params[0].params[0]", + "$[0][1].params[1].params[0]" + ], + "answer": ["locate_xy", "135", "-20"], + "points": 2.43, + "desc": "문제 2/마법사/[시작]의 세부 동작 1/x: '135' y: '-20' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][2].params[0].params[0]", + "answer": "180", + "points": 2.43, + "desc": "문제 2/마법사/[시작]의 세부 동작 2/크기를 '180' 으로 정하기" + }, + { + "ele": "$[0][3].params[*].params", + "answer": ["마법 실험을 해봐야지!", "2"], + "points": 2.43, + "desc": "문제 2/마법사/[시작]의 세부 동작 3/'마법 실험을 해봐야지!' 를 '2' 초 동안 '말하기'" + } + ] + }, + "5-0": { + "type": "script", + "ele": "$.objects[?(@.name=~'마법의 약')].script", + "blocks": [ + { + "ele": "$[0][0].type", + "answer": "when_run_button_click", + "points": 2.43, + "desc": "문제 2/마법의 약/시작/시작하기 버튼을 클릭했을 때" + }, + { + "ele": [ + "$[0][1].type", + "$[0][1].params[0].params[0]", + "$[0][1].params[1].params[0]" + ], + "answer": ["locate_xy", "-40", "10"], + "points": 2.43, + "desc": "문제 2/마법의 약/[시작]의 세부 동작 1/x: '-40' y: '10' 위치로 이동하기", + "type": "list" + }, + { + "ele": "$[0][2].params[0].params[0]", + "answer": "50", + "points": 2.43, + "desc": "문제 2/마법의 약/[시작]의 세부 동작 2/크기를 '50' 으로 정하기" + }, + { + "ele": ["$[0][3].type", "$[0][3].params[0]"], + "answer": ["repeat_inf", null], + "points": 2.43, + "desc": "문제 2/마법의 약/반복/계속 반복하기", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][0].type", + "answer": "hide", + "points": 2.43, + "desc": "문제 2/마법의 약/[반복]의 세부 동작 1/모양 숨기기" + }, + { + "ele": [ + "$[0][3].statements[0][1].type", + "$[0][3].statements[0][1].params[0].params[1].params[0]", + "$[0][3].statements[0][1].params[0].params[3].params[0]" + ], + "answer": ["locate_x", "-160", "60"], + "points": 2.43, + "desc": "문제 2/마법의 약/[반복]의 세부 동작 2/x: '-160 부터 60 사이의 무작위 수' 위치로 이동하기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][2].type", + "$[0][3].statements[0][2].params[0].params[0]" + ], + "answer": ["wait_second", "2"], + "points": 2.43, + "desc": "문제 2/마법의 약/[반복]의 세부 동작 3/ '2' 초 기다리기", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][3].type", + "answer": "show", + "points": 2.43, + "desc": "문제 2/마법의 약/[반복]의 세부 동작 4/모양 보이기" + }, + { + "ele": [ + "$[0][3].statements[0][4].type", + "$[0][3].statements[0][4].params[0].params[0]" + ], + "answer": ["wait_second", "0.5"], + "points": 2.43, + "desc": "문제 2/마법의 약/[반복]의 세부 동작 5/'0.5' 초 기다리기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][5].type", + "$[0][3].statements[0][5].params[0].type" + ], + "answer": ["_if", "reach_something"], + "points": 2.43, + "desc": "문제 2/마법의 약/만일/만일 '새로운 약' 에 닿았는가? 라면", + "type": "list" + }, + { + "ele": "$[0][3].statements[0][5].statements[0][0].params[0].params[0]", + "answer": "100", + "points": 2.43, + "desc": "문제 2/마법의 약/[만일]의 세부 동작 1/크기를 '100' 으로 정하기" + }, + { + "ele": [ + "$[0][3].statements[0][5].statements[0][1].type", + "$[0][3].statements[0][5].statements[0][1].params[0]", + "$[0][3].statements[0][5].statements[0][1].params[1].params[0]" + ], + "answer": ["add_effect_amount", "color", "70"], + "points": 2.43, + "desc": "문제 2/마법의 약/[만일]의 세부 동작 2/'색깔' 효과를 '70' 만큼 주기", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][5].statements[0][2].type", + "$[0][3].statements[0][5].statements[0][2].params[0].params[0]", + "$[0][3].statements[0][5].statements[0][2].params[1]" + ], + "answer": ["dialog", "마법 성공", "speak"], + "points": 2.43, + "desc": "문제 2/마법의 약/[만일]의 세부 동작 3/'마법 성공' 을 '말하기'", + "type": "list" + }, + { + "ele": [ + "$[0][3].statements[0][5].statements[0][3].type", + "$[0][3].statements[0][5].statements[0][3].params[0]" + ], + "answer": ["stop_object", "all"], + "points": 2.43, + "desc": "문제 2/마법의 약/[만일]의 세부 동작 4/'모든' 코드 멈추기", + "type": "list" + } + ] + } +}