prthm11 commited on
Commit
38ca3ae
·
verified ·
1 Parent(s): 40f879b

Update utils/block_relation_builder.py

Browse files
Files changed (1) hide show
  1. utils/block_relation_builder.py +73 -42
utils/block_relation_builder.py CHANGED
@@ -2300,9 +2300,12 @@ def generate_plan(generated_input, opcode_keys, pseudo_code):
2300
  menu_block_id = _register_block("control_create_clone_of_menu", key, True, pick_key, all_generated_blocks, fields={"CLONE_OPTION": [option_val, None]})
2301
  info["inputs"]["CLONE_OPTION"] = {"kind": "block", "block": menu_block_id}
2302
  elif opcode in ["sound_playuntildone", "sound_play"]:
2303
- m = re.search(r"(?:play sound|start sound)\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
 
2304
  if m:
2305
- option = m.group(1).strip()
 
 
2306
  menu_block_id = _register_block("sound_sounds_menu", key, True, pick_key, all_generated_blocks, fields={"SOUND_MENU": [option, None]})
2307
  info["inputs"]["SOUND_MENU"] = {"kind": "block", "block": menu_block_id}
2308
  elif opcode == "looks_switchcostumeto":
@@ -3147,8 +3150,10 @@ def _find_all_opcodes(code_block: str) -> list[str]:
3147
  (r"\(?username\)?", "sensing_username"), #(to test muliple bracket and alone should treet as the keyword)
3148
 
3149
  # --- Sound Blocks ---
3150
- (r"play sound \[.+? v\] until done", "sound_playuntildone"),
3151
- (r"start sound \[.+? v\]", "sound_play"),
 
 
3152
  (r"stop all sounds", "sound_stopallsounds"),
3153
  (r"change volume by\s*(?:\((.+?)\)|\[(.+?)\]|(.+))", "sound_changevolumeby"),
3154
  (r"""set\ volume\ to\s+\(?\s*(?:-?\d+(?:\.\d+)?|\[?[a-zA-Z_][\w\s]*\]?(?:\ v)?)\s*\)?\s*%?""", "sound_setvolumeto"),
@@ -3252,49 +3257,75 @@ def analyze_opcode_counts(pseudo_code: str) -> list[dict]:
3252
  #--------------------------------------------------[Helper function to seperate an correct the json]-------------------------------------------------------------
3253
  #################################################################################################################################################################
3254
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3255
  def separate_scripts(pseudocode_string):
3256
  """
3257
- Separates a block of Scratch pseudocode into a list of individual scripts.
 
 
 
 
 
 
 
 
 
 
 
 
3258
 
3259
- This function finds the start of each "hat" block and slices the
3260
- original string to capture the full code block for each script,
3261
- providing a more robust and reliable separation.
3262
 
3263
- Args:
3264
- pseudocode_string (str): A string containing Scratch pseudocode.
 
 
 
3265
 
3266
- Returns:
3267
- list: A list of strings, where each string is a complete,
3268
- separated script.
3269
- """
3270
- # Define the "hat" block patterns with more robust regex.
3271
- # We use a non-capturing group (?:...) for the patterns.
3272
- # We use a logical OR (|) to combine them into a single pattern.
3273
- delimiter_patterns = (
3274
- r"when green flag clicked|when flag clicked|when \S+ key pressed|"
3275
- r"when this sprite clicked|when backdrop switches to \[.*?\]|"
3276
- r"when I receive \[.*?\]|when \[.*?\] > \[.*?\]"
3277
- )
3278
-
3279
- # Use re.finditer to get an iterator of all hat block matches.
3280
- # The `re.DOTALL` flag allows the '.' to match newlines.
3281
- matches = list(re.finditer(delimiter_patterns, pseudocode_string, flags=re.DOTALL | re.IGNORECASE))
3282
-
3283
- scripts = []
3284
- # If no matches are found, return an empty list.
3285
- if not matches:
3286
- return []
3287
-
3288
- # Iterate through the matches to slice the original string.
3289
- for i in range(len(matches)):
3290
- start = matches[i].start()
3291
- end = matches[i+1].start() if i + 1 < len(matches) else len(pseudocode_string)
3292
-
3293
- # Slice the pseudocode string from the start of one match to the start
3294
- # of the next, or to the end of the string.
3295
- script = pseudocode_string[start:end]
3296
- scripts.append(script.strip())
3297
-
3298
  return scripts
3299
 
3300
  def transform_logic_to_action_flow(source_data, description=""):
 
2300
  menu_block_id = _register_block("control_create_clone_of_menu", key, True, pick_key, all_generated_blocks, fields={"CLONE_OPTION": [option_val, None]})
2301
  info["inputs"]["CLONE_OPTION"] = {"kind": "block", "block": menu_block_id}
2302
  elif opcode in ["sound_playuntildone", "sound_play"]:
2303
+ # m = re.search(r"(?:play sound|start sound)\s*\[([^\]]+)\s*v\]", stmt_for_parse, re.IGNORECASE)
2304
+ m = re.search(r"(?:play sound|start sound)\s*(?:\[\s*([^\]]+?)\s*v\]|\(?\s*([^)]+)\s*\)?)",stmt_for_parse,re.IGNORECASE)
2305
  if m:
2306
+ # option = m.group(1).strip()
2307
+ option = m.group(1) or m.group(2)
2308
+ print("sounds option content--------->",option)
2309
  menu_block_id = _register_block("sound_sounds_menu", key, True, pick_key, all_generated_blocks, fields={"SOUND_MENU": [option, None]})
2310
  info["inputs"]["SOUND_MENU"] = {"kind": "block", "block": menu_block_id}
2311
  elif opcode == "looks_switchcostumeto":
 
3150
  (r"\(?username\)?", "sensing_username"), #(to test muliple bracket and alone should treet as the keyword)
3151
 
3152
  # --- Sound Blocks ---
3153
+ # (r"play sound \[.+? v\] until done", "sound_playuntildone"),
3154
+ # (r"start sound \[.+? v\]", "sound_play"),
3155
+ (r"play sound\s+(?:\[\s*.+?\s*v\]|\(?\s*.+?\s*\)?)\s+until done", "sound_playuntildone"),
3156
+ (r"start sound\s+(?:\[\s*.+?\s*v\]|\(?\s*.+?\s*\)?)", "sound_play"),
3157
  (r"stop all sounds", "sound_stopallsounds"),
3158
  (r"change volume by\s*(?:\((.+?)\)|\[(.+?)\]|(.+))", "sound_changevolumeby"),
3159
  (r"""set\ volume\ to\s+\(?\s*(?:-?\d+(?:\.\d+)?|\[?[a-zA-Z_][\w\s]*\]?(?:\ v)?)\s*\)?\s*%?""", "sound_setvolumeto"),
 
3257
  #--------------------------------------------------[Helper function to seperate an correct the json]-------------------------------------------------------------
3258
  #################################################################################################################################################################
3259
 
3260
+ # def separate_scripts(pseudocode_string):
3261
+ # """
3262
+ # Separates a block of Scratch pseudocode into a list of individual scripts.
3263
+
3264
+ # This function finds the start of each "hat" block and slices the
3265
+ # original string to capture the full code block for each script,
3266
+ # providing a more robust and reliable separation.
3267
+
3268
+ # Args:
3269
+ # pseudocode_string (str): A string containing Scratch pseudocode.
3270
+
3271
+ # Returns:
3272
+ # list: A list of strings, where each string is a complete,
3273
+ # separated script.
3274
+ # """
3275
+ # # Define the "hat" block patterns with more robust regex.
3276
+ # # We use a non-capturing group (?:...) for the patterns.
3277
+ # # We use a logical OR (|) to combine them into a single pattern.
3278
+ # delimiter_patterns = (
3279
+ # r"when green flag clicked|when flag clicked|when \S+ key pressed|"
3280
+ # r"when this sprite clicked|when backdrop switches to \[.*?\]|"
3281
+ # r"when I receive \[.*?\]|when \[.*?\] > \[.*?\]"
3282
+ # )
3283
+
3284
+ # # Use re.finditer to get an iterator of all hat block matches.
3285
+ # # The `re.DOTALL` flag allows the '.' to match newlines.
3286
+ # matches = list(re.finditer(delimiter_patterns, pseudocode_string, flags=re.DOTALL | re.IGNORECASE))
3287
+
3288
+ # scripts = []
3289
+ # # If no matches are found, return an empty list.
3290
+ # if not matches:
3291
+ # return []
3292
+
3293
+ # # Iterate through the matches to slice the original string.
3294
+ # for i in range(len(matches)):
3295
+ # start = matches[i].start()
3296
+ # end = matches[i+1].start() if i + 1 < len(matches) else len(pseudocode_string)
3297
+
3298
+ # # Slice the pseudocode string from the start of one match to the start
3299
+ # # of the next, or to the end of the string.
3300
+ # script = pseudocode_string[start:end]
3301
+ # scripts.append(script.strip())
3302
+
3303
+ # return scripts
3304
  def separate_scripts(pseudocode_string):
3305
  """
3306
+ Split a block of Scratch pseudocode into individual scripts.
3307
+ Each script starts at a 'when ...' hat block that appears at the start
3308
+ of a line (leading whitespace allowed).
3309
+ """
3310
+ # Robust, non-capturing hat-block patterns (no capturing groups!)
3311
+ patterns = [
3312
+ r"when\s+(?:green\s+flag\s+)?click(?:ed)?\b", # when flag clicked / when green flag clicked
3313
+ r"when\s+(?:\S+(?:\s+\S+)*)\s+key\s+press(?:ed)?\b", # when space key pressed / when up arrow key press
3314
+ r"when\s+this\s+sprite\s+click(?:ed)?\b", # when this sprite clicked
3315
+ r"when\s+backdrop\s+switch(?:es|ed)?\s+to\s*\[[^\]]*\]", # when backdrop switches to [..]
3316
+ r"when\s+I\s+receive(?:d)?\s*\[[^\]]*\]", # when I receive [..] / when I received [..]
3317
+ r"when\s*\[[^\]]*\]\s*>\s*\[[^\]]*\]" # when [sensor] > [value]
3318
+ ]
3319
 
3320
+ # Build a lookahead that finds positions just before a hat block at line-start
3321
+ lookahead = r"(?=^\s*(?:{}))".format("|".join(patterns))
 
3322
 
3323
+ # Use MULTILINE so ^ matches start of lines, DOTALL to allow patterns that may include brackets/newlines as needed
3324
+ parts = re.split(lookahead, pseudocode_string, flags=re.IGNORECASE | re.MULTILINE | re.DOTALL)
3325
+
3326
+ # Filter out empties and strip leading/trailing whitespace/newlines
3327
+ scripts = [p.strip() for p in parts if p and p.strip()]
3328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3329
  return scripts
3330
 
3331
  def transform_logic_to_action_flow(source_data, description=""):