Spaces:
Running
Running
Update utils/block_relation_builder.py
Browse files- utils/block_relation_builder.py +93 -49
utils/block_relation_builder.py
CHANGED
@@ -4,7 +4,7 @@ import re
|
|
4 |
from collections import defaultdict
|
5 |
import secrets
|
6 |
import string
|
7 |
-
from typing import Dict, Any, TypedDict
|
8 |
|
9 |
|
10 |
#################################################################################################################################################################
|
@@ -1871,7 +1871,8 @@ def classify(line):
|
|
1871 |
if l.startswith("if <"): return "control_if", "c_block"
|
1872 |
if l.startswith("repeat until <"): return "control_repeat_until", "c_block"
|
1873 |
# Updated regex for stop block to handle different options
|
1874 |
-
if re.match(r"stop \[(all|this script|other scripts in sprite)\s*v\]", l): return "control_stop", "cap"
|
|
|
1875 |
if l.startswith("create clone of"): return "control_create_clone_of", "stack"
|
1876 |
if l == "delete this clone": return "control_delete_this_clone", "cap"
|
1877 |
|
@@ -2572,8 +2573,9 @@ def process_scratch_blocks(all_generated_blocks, generated_output_json):
|
|
2572 |
for input_name, input_data in all_gen_block_data["inputs"].items():
|
2573 |
if input_name == "BROADCAST_INPUT":
|
2574 |
# Special handling for BROADCAST_INPUT (type 11)
|
2575 |
-
if isinstance(input_data, dict) and input_data.get("kind") == "
|
2576 |
-
|
|
|
2577 |
broadcast_id = broadcast_id_map[menu_option]
|
2578 |
processed_block["inputs"][input_name] = [
|
2579 |
1,
|
@@ -2794,12 +2796,66 @@ def process_scratch_blocks(all_generated_blocks, generated_output_json):
|
|
2794 |
|
2795 |
processed_blocks[block_id] = processed_block
|
2796 |
return processed_blocks
|
2797 |
-
|
2798 |
#################################################################################################################################################################
|
2799 |
#--------------------------------------------------[Unique secret key for skelton json to make sure it donot overwrite each other]-------------------------------
|
2800 |
#################################################################################################################################################################
|
2801 |
|
2802 |
-
def rename_blocks(block_json:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2803 |
"""
|
2804 |
Replace each block key in block_json and each identifier in opcode_count
|
2805 |
with a newly generated secure token.
|
@@ -2895,60 +2951,39 @@ def variable_intialization(project_data):
|
|
2895 |
initial_value = ""
|
2896 |
if value_input and isinstance(value_input, list) and len(value_input) > 1 and \
|
2897 |
isinstance(value_input[1], list) and len(value_input[1]) > 1:
|
2898 |
-
|
2899 |
-
if value_input[1][0] == 10: # Direct value like [10, "0"]
|
2900 |
initial_value = str(value_input[1][1])
|
2901 |
-
elif value_input[1][0] == 12 and len(value_input) > 2 and isinstance(value_input[2], list) and value_input[2][0] == 10:
|
2902 |
-
|
2903 |
-
elif isinstance(value_input[1], (str, int, float)):
|
2904 |
initial_value = str(value_input[1])
|
2905 |
-
|
2906 |
-
|
2907 |
-
# Add/update the variable in the Stage's 'variables' with its initial value
|
2908 |
stage_target["variables"][var_id] = [var_name, initial_value]
|
2909 |
|
2910 |
-
|
2911 |
for key, value in obj.items():
|
2912 |
-
# Process variable definitions in 'fields' (for blocks that define variables like 'show variable')
|
2913 |
-
if key == "VARIABLE" and isinstance(value, list) and len(value) == 2:
|
2914 |
-
var_name = value[0]
|
2915 |
-
var_id = value[1]
|
2916 |
-
# Only add if not already defined with an initial value from set_variableto
|
2917 |
-
if var_id not in stage_target["variables"]:
|
2918 |
-
stage_target["variables"][var_id] = [var_name, ""] # Default to empty string if no initial value found yet
|
2919 |
-
elif stage_target["variables"][var_id][0] != var_name: # Update name if ID exists but name is different
|
2920 |
-
stage_target["variables"][var_id][0] = var_name
|
2921 |
-
|
2922 |
-
|
2923 |
# Process broadcast definitions in 'inputs' (BROADCAST_INPUT)
|
2924 |
-
|
2925 |
-
|
2926 |
broadcast_name = value[1][1]
|
2927 |
broadcast_id = value[1][2]
|
2928 |
-
# Add/update the broadcast in the Stage's 'broadcasts'
|
2929 |
stage_target["broadcasts"][broadcast_id] = broadcast_name
|
2930 |
|
2931 |
# Process broadcast definitions in 'fields' (BROADCAST_OPTION)
|
2932 |
elif key == "BROADCAST_OPTION" and isinstance(value, list) and len(value) == 2:
|
2933 |
broadcast_name = value[0]
|
2934 |
broadcast_id = value[1]
|
2935 |
-
# Add/update the broadcast in the Stage's 'broadcasts'
|
2936 |
stage_target["broadcasts"][broadcast_id] = broadcast_name
|
2937 |
-
|
2938 |
# Recursively call for nested dictionaries or lists
|
2939 |
process_dict(value)
|
|
|
2940 |
elif isinstance(obj, list):
|
2941 |
for i, item in enumerate(obj):
|
2942 |
# Process variable references in 'inputs' (like [12, "score", "id"])
|
2943 |
if isinstance(item, list) and len(item) == 3 and item[0] == 12:
|
2944 |
var_name = item[1]
|
2945 |
var_id = item[2]
|
2946 |
-
# Only add if not already defined with an initial value from set_variableto
|
2947 |
if var_id not in stage_target["variables"]:
|
2948 |
-
stage_target["variables"][var_id] = [var_name, ""]
|
2949 |
-
elif stage_target["variables"][var_id][0] != var_name: # Update name if ID exists but name is different
|
2950 |
-
stage_target["variables"][var_id][0] = var_name
|
2951 |
-
|
2952 |
process_dict(item)
|
2953 |
|
2954 |
# Iterate through all targets to process their blocks
|
@@ -3030,14 +3065,15 @@ def deduplicate_variables(project_data):
|
|
3030 |
def variable_adder_main(project_data):
|
3031 |
try:
|
3032 |
declare_variable_json= variable_intialization(project_data)
|
|
|
3033 |
except Exception as e:
|
3034 |
print(f"Error error in the variable initialization opcodes: {e}")
|
3035 |
try:
|
3036 |
processed_json= deduplicate_variables(declare_variable_json)
|
3037 |
-
|
|
|
3038 |
except Exception as e:
|
3039 |
print(f"Error error in the variable initialization opcodes: {e}")
|
3040 |
-
|
3041 |
#################################################################################################################################################################
|
3042 |
#--------------------------------------------------[Helper main function]----------------------------------------------------------------------------------------
|
3043 |
#################################################################################################################################################################
|
@@ -3066,18 +3102,24 @@ def block_builder(opcode_count,pseudo_code):
|
|
3066 |
#################################################################################################################################################################
|
3067 |
|
3068 |
initial_opcode_counts = [
|
3069 |
-
{
|
3070 |
-
|
3071 |
-
|
3072 |
-
},
|
3073 |
-
{
|
3074 |
-
|
3075 |
-
|
3076 |
-
}
|
3077 |
]
|
3078 |
pseudo_code="""
|
3079 |
-
when I receive [Game
|
3080 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
3081 |
end
|
3082 |
"""
|
3083 |
# print(pseudo_code)
|
@@ -3085,8 +3127,10 @@ end
|
|
3085 |
# all_generated_blocks = generate_plan(generated_output_json, initial_opcode_occurrences, pseudo_code)
|
3086 |
# processed_blocks= process_scratch_blocks(all_generated_blocks, generated_output_json)
|
3087 |
# renamed_blocks, renamed_counts = rename_blocks(processed_blocks, initial_opcode_occurrences)
|
3088 |
-
# print(all_generated_blocks)
|
3089 |
# print("--------------\n\n")
|
3090 |
# print(processed_blocks)
|
3091 |
# print("--------------\n\n")
|
|
|
|
|
3092 |
# print(renamed_blocks)
|
|
|
4 |
from collections import defaultdict
|
5 |
import secrets
|
6 |
import string
|
7 |
+
from typing import Dict, Any, TypedDict,Tuple
|
8 |
|
9 |
|
10 |
#################################################################################################################################################################
|
|
|
1871 |
if l.startswith("if <"): return "control_if", "c_block"
|
1872 |
if l.startswith("repeat until <"): return "control_repeat_until", "c_block"
|
1873 |
# Updated regex for stop block to handle different options
|
1874 |
+
#if re.match(r"stop \[(all|this script|other scripts in sprite)\s*v\]", l): return "control_stop", "cap"
|
1875 |
+
if re.match(r"stop\s*(?:[\[(]?\s*(all|this script|other scripts in sprite)\s*[\])]?$)", l, re.IGNORECASE): return "control_stop", "cap"
|
1876 |
if l.startswith("create clone of"): return "control_create_clone_of", "stack"
|
1877 |
if l == "delete this clone": return "control_delete_this_clone", "cap"
|
1878 |
|
|
|
2573 |
for input_name, input_data in all_gen_block_data["inputs"].items():
|
2574 |
if input_name == "BROADCAST_INPUT":
|
2575 |
# Special handling for BROADCAST_INPUT (type 11)
|
2576 |
+
if isinstance(input_data, dict) and input_data.get("kind") == "value":
|
2577 |
+
# This is the new logic to handle a direct value for broadcast
|
2578 |
+
menu_option = input_data.get("value", "message1")
|
2579 |
broadcast_id = broadcast_id_map[menu_option]
|
2580 |
processed_block["inputs"][input_name] = [
|
2581 |
1,
|
|
|
2796 |
|
2797 |
processed_blocks[block_id] = processed_block
|
2798 |
return processed_blocks
|
2799 |
+
|
2800 |
#################################################################################################################################################################
|
2801 |
#--------------------------------------------------[Unique secret key for skelton json to make sure it donot overwrite each other]-------------------------------
|
2802 |
#################################################################################################################################################################
|
2803 |
|
2804 |
+
def rename_blocks(block_json: Dict[str, Any], opcode_count: Dict[str, list]) -> Tuple[Dict[str, Any], Dict[str, list]]:
|
2805 |
+
"""
|
2806 |
+
Replace each block key in block_json and each identifier in opcode_count
|
2807 |
+
with a newly generated secure token, ensuring all references are updated.
|
2808 |
+
|
2809 |
+
Args:
|
2810 |
+
block_json: Mapping of block_key -> block_data.
|
2811 |
+
opcode_count: Mapping of opcode -> list of block_keys.
|
2812 |
+
|
2813 |
+
Returns:
|
2814 |
+
A tuple of (new_block_json, new_opcode_count) with updated keys.
|
2815 |
+
"""
|
2816 |
+
token_map = {}
|
2817 |
+
|
2818 |
+
# Step 1: Generate a secure token mapping for every existing block key
|
2819 |
+
for old_key in block_json.keys():
|
2820 |
+
while True:
|
2821 |
+
new_key = generate_secure_token()
|
2822 |
+
if new_key not in token_map.values():
|
2823 |
+
break
|
2824 |
+
token_map[old_key] = new_key
|
2825 |
+
|
2826 |
+
new_block_json = {}
|
2827 |
+
|
2828 |
+
# Step 2: Rebuild block_json with new keys and update all references
|
2829 |
+
for old_key, block in block_json.items():
|
2830 |
+
new_key = token_map[old_key]
|
2831 |
+
new_block_json[new_key] = block.copy()
|
2832 |
+
|
2833 |
+
# Update parent and next references
|
2834 |
+
if 'parent' in block and block['parent'] in token_map:
|
2835 |
+
new_block_json[new_key]['parent'] = token_map[block['parent']]
|
2836 |
+
if 'next' in block and block['next'] in token_map:
|
2837 |
+
new_block_json[new_key]['next'] = token_map[block['next']]
|
2838 |
+
|
2839 |
+
# Update inputs that reference blocks
|
2840 |
+
if 'inputs' in block:
|
2841 |
+
for inp_key, inp_val in block['inputs'].items():
|
2842 |
+
# This handles references like [2, 'block_key']
|
2843 |
+
if isinstance(inp_val, list) and len(inp_val) == 2:
|
2844 |
+
idx, ref = inp_val
|
2845 |
+
if isinstance(ref, str) and ref in token_map:
|
2846 |
+
new_block_json[new_key]['inputs'][inp_key] = [idx, token_map[ref]]
|
2847 |
+
# This new block handles references like [3, 'block_key', [10, '']]
|
2848 |
+
elif isinstance(inp_val, list) and len(inp_val) == 3:
|
2849 |
+
idx, ref, rest = inp_val
|
2850 |
+
if isinstance(ref, str) and ref in token_map:
|
2851 |
+
new_block_json[new_key]['inputs'][inp_key] = [idx, token_map[ref], rest]
|
2852 |
+
|
2853 |
+
# Step 3: Update opcode count map
|
2854 |
+
new_opcode_count = {}
|
2855 |
+
for opcode, key_list in opcode_count.items():
|
2856 |
+
new_opcode_count[opcode] = [token_map.get(k, k) for k in key_list]
|
2857 |
+
|
2858 |
+
return new_block_json, new_opcode_count
|
2859 |
"""
|
2860 |
Replace each block key in block_json and each identifier in opcode_count
|
2861 |
with a newly generated secure token.
|
|
|
2951 |
initial_value = ""
|
2952 |
if value_input and isinstance(value_input, list) and len(value_input) > 1 and \
|
2953 |
isinstance(value_input[1], list) and len(value_input[1]) > 1:
|
2954 |
+
if value_input[1][0] == 10:
|
|
|
2955 |
initial_value = str(value_input[1][1])
|
2956 |
+
elif value_input[1][0] == 12 and len(value_input) > 2 and isinstance(value_input[2], list) and value_input[2][0] == 10:
|
2957 |
+
initial_value = str(value_input[2][1])
|
2958 |
+
elif isinstance(value_input[1], (str, int, float)):
|
2959 |
initial_value = str(value_input[1])
|
|
|
|
|
|
|
2960 |
stage_target["variables"][var_id] = [var_name, initial_value]
|
2961 |
|
|
|
2962 |
for key, value in obj.items():
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2963 |
# Process broadcast definitions in 'inputs' (BROADCAST_INPUT)
|
2964 |
+
if key == "BROADCAST_INPUT" and isinstance(value, list) and len(value) == 2 and \
|
2965 |
+
isinstance(value[1], list) and len(value[1]) == 3 and value[1][0] == 11:
|
2966 |
broadcast_name = value[1][1]
|
2967 |
broadcast_id = value[1][2]
|
|
|
2968 |
stage_target["broadcasts"][broadcast_id] = broadcast_name
|
2969 |
|
2970 |
# Process broadcast definitions in 'fields' (BROADCAST_OPTION)
|
2971 |
elif key == "BROADCAST_OPTION" and isinstance(value, list) and len(value) == 2:
|
2972 |
broadcast_name = value[0]
|
2973 |
broadcast_id = value[1]
|
|
|
2974 |
stage_target["broadcasts"][broadcast_id] = broadcast_name
|
2975 |
+
|
2976 |
# Recursively call for nested dictionaries or lists
|
2977 |
process_dict(value)
|
2978 |
+
|
2979 |
elif isinstance(obj, list):
|
2980 |
for i, item in enumerate(obj):
|
2981 |
# Process variable references in 'inputs' (like [12, "score", "id"])
|
2982 |
if isinstance(item, list) and len(item) == 3 and item[0] == 12:
|
2983 |
var_name = item[1]
|
2984 |
var_id = item[2]
|
|
|
2985 |
if var_id not in stage_target["variables"]:
|
2986 |
+
stage_target["variables"][var_id] = [var_name, ""]
|
|
|
|
|
|
|
2987 |
process_dict(item)
|
2988 |
|
2989 |
# Iterate through all targets to process their blocks
|
|
|
3065 |
def variable_adder_main(project_data):
|
3066 |
try:
|
3067 |
declare_variable_json= variable_intialization(project_data)
|
3068 |
+
print("declare_variable_json------->",declare_variable_json)
|
3069 |
except Exception as e:
|
3070 |
print(f"Error error in the variable initialization opcodes: {e}")
|
3071 |
try:
|
3072 |
processed_json= deduplicate_variables(declare_variable_json)
|
3073 |
+
print("processed_json------->",processed_json)
|
3074 |
+
return processed_json
|
3075 |
except Exception as e:
|
3076 |
print(f"Error error in the variable initialization opcodes: {e}")
|
|
|
3077 |
#################################################################################################################################################################
|
3078 |
#--------------------------------------------------[Helper main function]----------------------------------------------------------------------------------------
|
3079 |
#################################################################################################################################################################
|
|
|
3102 |
#################################################################################################################################################################
|
3103 |
|
3104 |
initial_opcode_counts = [
|
3105 |
+
{"opcode": "event_whenbroadcastreceived","count": 1},
|
3106 |
+
{"opcode": "control_forever","count": 1},
|
3107 |
+
{"opcode": "control_if","count": 1},
|
3108 |
+
{"opcode": "sensing_istouching","count": 1},
|
3109 |
+
{"opcode": "looks_hide","count": 1},
|
3110 |
+
{"opcode": "looks_switchbackdropto","count": 1},
|
3111 |
+
{"opcode": "event_broadcast","count": 1},
|
3112 |
+
{"opcode": "control_stop","count": 1}
|
3113 |
]
|
3114 |
pseudo_code="""
|
3115 |
+
when I receive [Game Start v]
|
3116 |
+
forever
|
3117 |
+
if <touching [obstacle v]?> then
|
3118 |
+
hide
|
3119 |
+
switch backdrop to [loose v]
|
3120 |
+
broadcast [Game Over v]
|
3121 |
+
stop all
|
3122 |
+
end
|
3123 |
end
|
3124 |
"""
|
3125 |
# print(pseudo_code)
|
|
|
3127 |
# all_generated_blocks = generate_plan(generated_output_json, initial_opcode_occurrences, pseudo_code)
|
3128 |
# processed_blocks= process_scratch_blocks(all_generated_blocks, generated_output_json)
|
3129 |
# renamed_blocks, renamed_counts = rename_blocks(processed_blocks, initial_opcode_occurrences)
|
3130 |
+
# #print(all_generated_blocks)
|
3131 |
# print("--------------\n\n")
|
3132 |
# print(processed_blocks)
|
3133 |
# print("--------------\n\n")
|
3134 |
+
# print(initial_opcode_occurrences)
|
3135 |
+
# print("--------------\n\n")
|
3136 |
# print(renamed_blocks)
|