prthm11 commited on
Commit
b6f609b
·
verified ·
1 Parent(s): bfc573a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +249 -117
app.py CHANGED
@@ -17,11 +17,45 @@ from langgraph.graph import StateGraph, END
17
  import uuid
18
  import shutil, time, functools
19
  from langchain_experimental.open_clip.open_clip import OpenCLIPEmbeddings
 
20
  # from matplotlib.offsetbox import OffsetImage, AnnotationBbox
21
  from io import BytesIO
22
  from pathlib import Path
23
  import os
24
  from utils.block_relation_builder import block_builder, variable_adder_main
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  def log_execution_time(func):
27
  @functools.wraps(func)
@@ -233,6 +267,11 @@ agent = create_react_agent(
233
  prompt=SYSTEM_PROMPT
234
  )
235
 
 
 
 
 
 
236
  agent_json_resolver = create_react_agent(
237
  model=llm,
238
  tools=[], # No specific tools are defined here, but could be added later
@@ -489,6 +528,56 @@ def clean_base64_for_model(raw_b64):
489
  # 6. Return with the correct data URI prefix
490
  return f"data:image/png;base64,{clean_b64}"
491
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
 
493
  # Node 1: Logic updating if any issue here
494
  def pseudo_generator_node(state: GameState):
@@ -562,7 +651,7 @@ If you find any "Code-Blocks" then,
562
 
563
  3. **Pseudo‑code formatting**:
564
  - Represent each block or nested block on its own line.
565
- - Indent nested blocks by 4 spaces under their parent (`forever`, `if`, etc.).
566
  - No comments or explanatory text—just the block sequence.
567
  - a natural language breakdown of each step taken after the event, formatted as a multi-line string representing pseudo-code. Ensure clarity and granularity—each described action should map closely to a Scratch block or tight sequence.
568
 
@@ -573,71 +662,57 @@ If you find any "Code-Blocks" then,
573
 
574
  5. **Examples for reference**:
575
  **Correct** pattern for a simple start script:
576
- ```
577
- when green flag clicked
578
- switch backdrop to [blue sky v]
579
- set [score v] to (0)
580
- show variable [score v]
581
- broadcast [Game Start v]
582
- end
583
- ```
584
  **Correct** pattern for updating the high score variable handling:
585
- ```
586
- when I receive [Game Over v]
587
- if <((score)) > (([High Score v]))> then
588
- set [High Score v] to ([score v])
589
- end
590
- switch backdrop to [Game Over v]
591
- end
592
- ```
593
  **Correct** pattern for level up and increase difficulty use:
594
- ```
595
- when I receive [Level Up v]
596
- change [level v] by (1)
597
- set [ballSpeed v] to ((([ballSpeed v]) * (1.1)))
598
- end
599
- ```
600
  **Correct** pattern for jumping mechanics use:
601
- ```
602
- when [space v] key pressed
603
- if <((y position)) = (-100)> then
604
- repeat (5)
605
- change y by (100)
606
- wait (0.1) seconds
607
- change y by (-100)
608
- wait (0.1) seconds
609
- end
610
- end
611
- end
612
- ```
613
- **Correct** pattern for continuos moving objects use:
614
- ```
615
- when green flag clicked
616
- go to x: (240) y: (-100)
617
- set [speed v] to (-5)
618
- show variable [speed v]
619
- forever
620
- change x by ([speed v])
621
- if <((x position)) < (-240)> then
622
- go to x: (240) y: (-100)
623
- end
624
- end
625
- end
626
- ```
627
  **Correct** pattern for continuos moving objects use:
628
- ```
629
- when green flag clicked
630
- go to x: (240) y: (-100)
631
- set [speed v] to (-5)
632
- show variable [speed v]
633
- forever
634
- change x by ([speed v])
635
- if <((x position)) < (-240)> then
636
- go to x: (240) y: (-100)
637
- end
638
- end
639
- end
640
- ```
641
  6. **Donot** add any explaination of logic or comments to justify or explain just put the logic content in the json.
642
  7. **Output**:
643
  Return **only** a JSON object, using double quotes everywhere:
@@ -799,40 +874,41 @@ Each plan must include a **single Scratch Hat Block** (e.g., 'event_whenflagclic
799
  (([ballSpeed v]) * (1.1))
800
  ```
801
  - **Every hat block script must end** with a final `end` on its own line.
 
802
  3. **Opcode Lists**: include relevant Scratch opcodes grouped under `motion`, `control`, `operator`, `sensing`, `looks`, `sounds`, `events`, and `data`. List only the non-empty categories. Use exact opcodes.
803
  4. Few Example of content of logics inside for a specific plan as scratch pseudo-code:
804
  - example 1[continues moving objects]:
805
  ```
806
  when green flag clicked
807
- go to x: (240) y: (-100)
808
- set [speed v] to (-5)
809
- show variable [speed v]
810
- forever
811
- change x by ([speed v])
812
- if <((x position)) < (-240)> then
813
- go to x: (240) y: (-100)
814
- end
815
- end
816
  end
817
  ```
818
  - example 2[jumping script of an plan]:
819
  ```
820
  when [space v] key pressed
821
- if <((y position)) = (-100)> then
822
- repeat (5)
823
- change y by (100)
824
- wait (0.1) seconds
825
- change y by (-100)
826
- wait (0.1) seconds
827
- end
828
- end
829
  end
830
  ```
831
  - example 3 [pattern for level up and increase difficulty]:
832
  ```
833
  when I receive [Level Up v]
834
- change [level v] by (1)
835
- set [ballSpeed v] to ((([ballSpeed v]) * (1.1)))
836
  end
837
  ```
838
  5. Use target names exactly as listed in `Targets in Game`. Do NOT rename or invent new targets.
@@ -846,7 +922,7 @@ Each plan must include a **single Scratch Hat Block** (e.g., 'event_whenflagclic
846
  "plans": [
847
  {{
848
  "event": "event_whenflagclicked",
849
- "logic": "when green flag clicked\n switch backdrop to [backdrop1 v]\n set [score v] to 0\n show variable [score v]\n broadcast [Game Start v]",
850
  "motion": [],
851
  "control": [],
852
  "operator": [],
@@ -865,7 +941,7 @@ Each plan must include a **single Scratch Hat Block** (e.g., 'event_whenflagclic
865
  }},
866
  {{
867
  "event": "event_whenbroadcastreceived",
868
- "logic": "when I receive [Game Over v]\n if <(score) > (High Score)> then\n set [High Score v] to (score)\n end\n switch backdrop to [HighScore v]",
869
  "motion": [],
870
  "control": [
871
  "control_if"
@@ -890,7 +966,7 @@ Each plan must include a **single Scratch Hat Block** (e.g., 'event_whenflagclic
890
  "plans": [
891
  {{
892
  "event": "event_whenflagclicked",
893
- "logic": "when green flag clicked\n go to x: 240 y: -100\n end\n.",
894
  "motion": [
895
  "motion_gotoxy"
896
  ],
@@ -904,7 +980,7 @@ Each plan must include a **single Scratch Hat Block** (e.g., 'event_whenflagclic
904
  }},
905
  {{
906
  "event": "event_whenkeypressed",
907
- "logic": "when [space v] key pressed\n repeat (10)\n change y by (20)\n wait (0.1) seconds\n change y by (-20)\n end",
908
  "motion": [
909
  "motion_changeyby"
910
  ],
@@ -926,7 +1002,7 @@ Each plan must include a **single Scratch Hat Block** (e.g., 'event_whenflagclic
926
  "plans": [
927
  {{
928
  "event": "event_whenflagclicked",
929
- "logic": "when green flag clicked\n go to x: 240 y: -135\n forever\n glide 2 seconds to x: -240 y: -135\n if <(x position) < -235> then\n set x to 240\n end\n if <touching [Sprite1 v]?> then\n broadcast [Game Over v]\n stop [all v]\n end\n end",
930
  "motion": [
931
  "motion_gotoxy",
932
  "motion_glidesecstoxy",
@@ -1108,35 +1184,35 @@ Use sprite names exactly as provided in `sprite_names` (e.g., 'Sprite1', 'soccer
1108
  - example 1[continues moving objects]:
1109
  ```
1110
  when green flag clicked
1111
- go to x: (240) y: (-100)
1112
- set [speed v] to (-5)
1113
- show variable [speed v]
1114
- forever
1115
- change x by ([speed v])
1116
- if <((x position)) < (-240)> then
1117
- go to x: (240) y: (-100)
1118
- end
1119
- end
1120
  end
1121
  ```
1122
  - example 2[jumping script of an plan]:
1123
  ```
1124
  when [space v] key pressed
1125
- if <((y position)) = (-100)> then
1126
- repeat (5)
1127
- change y by (100)
1128
- wait (0.1) seconds
1129
- change y by (-100)
1130
- wait (0.1) seconds
1131
- end
1132
- end
1133
  end
1134
  ```
1135
  - example 3 [pattern for level up and increase difficulty]:
1136
  ```
1137
  when I receive [Level Up v]
1138
- change [level v] by (1)
1139
- set [ballSpeed v] to ((([ballSpeed v]) * (1.1)))
1140
  end
1141
  ```
1142
  6. Use target names exactly as listed in `Targets in Game`. Do NOT rename or invent new targets.
@@ -1150,7 +1226,7 @@ Use sprite names exactly as provided in `sprite_names` (e.g., 'Sprite1', 'soccer
1150
  "plans": [
1151
  {{
1152
  "event": "event_whenflagclicked",
1153
- "logic": "when green flag clicked\n switch backdrop to [backdrop1 v]\n set [score v] to 0\n show variable [score v]\n broadcast [Game Start v]",
1154
  "motion": [],
1155
  "control": [],
1156
  "operator": [],
@@ -1169,7 +1245,7 @@ Use sprite names exactly as provided in `sprite_names` (e.g., 'Sprite1', 'soccer
1169
  }},
1170
  {{
1171
  "event": "event_whenbroadcastreceived",
1172
- "logic": "when I receive [Game Over v]\n if <(score) > (High Score)> then\n set [High Score v] to (score)\n end\n switch backdrop to [HighScore v]",
1173
  "motion": [],
1174
  "control": [
1175
  "control_if"
@@ -1194,7 +1270,7 @@ Use sprite names exactly as provided in `sprite_names` (e.g., 'Sprite1', 'soccer
1194
  "plans": [
1195
  {{
1196
  "event": "event_whenflagclicked",
1197
- "logic": "when green flag clicked\n go to x: 240 y: -100\n end\n.",
1198
  "motion": [
1199
  "motion_gotoxy"
1200
  ],
@@ -1208,7 +1284,7 @@ Use sprite names exactly as provided in `sprite_names` (e.g., 'Sprite1', 'soccer
1208
  }},
1209
  {{
1210
  "event": "event_whenkeypressed",
1211
- "logic": "when [space v] key pressed\n repeat (10)\n change y by (20)\n wait (0.1) seconds\n change y by (-20)\n end",
1212
  "motion": [
1213
  "motion_changeyby"
1214
  ],
@@ -1230,7 +1306,7 @@ Use sprite names exactly as provided in `sprite_names` (e.g., 'Sprite1', 'soccer
1230
  "plans": [
1231
  {{
1232
  "event": "event_whenflagclicked",
1233
- "logic": "when green flag clicked\n go to x: 240 y: -135\n forever\n glide 2 seconds to x: -240 y: -135\n if <(x position) < -235> then\n set x to 240\n end\n if <touching [Sprite1 v]?> then\n broadcast [Game Over v]\n stop [all v]\n end\n end",
1234
  "motion": [
1235
  "motion_gotoxy",
1236
  "motion_glidesecstoxy",
@@ -1649,9 +1725,10 @@ def overall_block_builder_node_2(state: dict):
1649
  for plan_entry in sprite_actions_data.get("plans", []):
1650
  logic_sequence = str(plan_entry["logic"])
1651
  opcode_counts = plan_entry.get("opcode_counts", {})
1652
-
 
1653
  try:
1654
- generated_blocks = block_builder(opcode_counts, logic_sequence)
1655
 
1656
  # Ensure generated_blocks is a dictionary
1657
  if not isinstance(generated_blocks, dict):
@@ -2241,6 +2318,61 @@ def similarity_matching(sprites_data: str, project_folder: str) -> str:
2241
  "textToSpeechLanguage": None
2242
  }
2243
  final_project["targets"].insert(0, stage_obj)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2244
 
2245
  with open(project_json_path, 'w') as f:
2246
  json.dump(final_project, f, indent=2)
@@ -2400,7 +2532,7 @@ def convert_pdf_stream_to_images(pdf_stream: io.BytesIO, dpi=300):
2400
 
2401
  def delay_for_tpm_node(state: GameState):
2402
  logger.info("--- Running DelayForTPMNode ---")
2403
- time.sleep(60) # Adjust the delay as needed
2404
  logger.info("Delay completed.")
2405
  return state
2406
 
@@ -2419,19 +2551,19 @@ workflow.add_node("plan_generator", overall_planner_node)
2419
  workflow.add_node("refined_planner", refined_planner_node) # Refines the action plan
2420
  workflow.add_node("opcode_counter", plan_opcode_counter_node)
2421
  workflow.add_node("block_builder", overall_block_builder_node_2)
2422
- # #workflow.add_node("variable_initializer", variable_adder_node)
2423
 
2424
  workflow.set_entry_point("pseudo_generator")
2425
  workflow.add_edge("pseudo_generator","time_delay_1")
2426
  workflow.add_edge("time_delay_1","plan_generator")
2427
  workflow.add_edge("plan_generator","time_delay_2")
2428
- workflow.add_edge("time_delay_2",END)
2429
  workflow.add_edge("time_delay_2","refined_planner")
2430
  workflow.add_edge("refined_planner","time_delay_3")
2431
  workflow.add_edge("time_delay_3","opcode_counter")
2432
  workflow.add_edge("opcode_counter","block_builder")
2433
- workflow.add_edge("block_builder",END)
2434
- #workflow.add_edge("variable_initializer", END)
2435
  app_graph = workflow.compile()
2436
 
2437
  # ============== Helper function to Upscale an Image ============== #
 
17
  import uuid
18
  import shutil, time, functools
19
  from langchain_experimental.open_clip.open_clip import OpenCLIPEmbeddings
20
+ from langchain_core.utils.utils import secret_from_env
21
  # from matplotlib.offsetbox import OffsetImage, AnnotationBbox
22
  from io import BytesIO
23
  from pathlib import Path
24
  import os
25
  from utils.block_relation_builder import block_builder, variable_adder_main
26
+ from langchain.chat_models import ChatOpenAI
27
+ from langchain_openai import ChatOpenAI
28
+ from pydantic import Field, SecretStr
29
+
30
+ os.environ["OPENROUTER_API_KEY"] = os.getenv("OPENROUTER_API_KEY", "default_key_or_placeholder")
31
+ class ChatOpenRouter(ChatOpenAI):
32
+ openai_api_key: Optional[SecretStr] = Field(
33
+ alias="api_key",
34
+ default_factory=secret_from_env("OPENROUTER_API_KEY", default=None),
35
+ )
36
+ @property
37
+ def lc_secrets(self) -> dict[str, str]:
38
+ return {"openai_api_key": "OPENROUTER_API_KEY"}
39
+
40
+ def __init__(self,
41
+ openai_api_key: Optional[str] = None,
42
+ **kwargs):
43
+ openai_api_key = (
44
+ openai_api_key or os.environ.get("OPENROUTER_API_KEY")
45
+ )
46
+ super().__init__(
47
+ base_url="https://openrouter.ai/api/v1",
48
+ openai_api_key=openai_api_key,
49
+ **kwargs
50
+ )
51
+
52
+ llm2 = ChatOpenRouter(
53
+ #model_name="deepseek/deepseek-r1-0528:free",
54
+ #model_name="google/gemini-2.0-flash-exp:free",
55
+ #model_name="deepseek/deepseek-v3-base:free",
56
+ model_name="deepseek/deepseek-r1:free"
57
+ )
58
+
59
 
60
  def log_execution_time(func):
61
  @functools.wraps(func)
 
267
  prompt=SYSTEM_PROMPT
268
  )
269
 
270
+ agent_2 = create_react_agent(
271
+ model=llm2,
272
+ tools=[], # No specific tools are defined here, but could be added later
273
+ prompt=SYSTEM_PROMPT
274
+ )
275
  agent_json_resolver = create_react_agent(
276
  model=llm,
277
  tools=[], # No specific tools are defined here, but could be added later
 
528
  # 6. Return with the correct data URI prefix
529
  return f"data:image/png;base64,{clean_b64}"
530
 
531
+ def format_scratch_pseudo_code(code_string):
532
+ """
533
+ Parses and formats Scratch pseudo-code with correct indentation,
534
+ specifically handling if/else/end structures correctly.
535
+
536
+ Args:
537
+ code_string (str): A string containing Scratch pseudo-code with
538
+ potentially inconsistent indentation.
539
+
540
+ Returns:
541
+ str: The correctly formatted and indented pseudo-code string.
542
+ """
543
+ lines = code_string.strip().split('\n')
544
+ formatted_lines = []
545
+ indent_level = 0
546
+
547
+ # Keywords that increase indentation for the NEXT line
548
+ indent_keywords = ['when', 'forever', 'if', 'repeat', 'else']
549
+
550
+ # Keywords that decrease indentation for the CURRENT line
551
+ unindent_keywords = ['end', 'else']
552
+
553
+ for line in lines:
554
+ stripped_line = line.strip()
555
+ if not stripped_line:
556
+ continue
557
+
558
+ # Check for keywords that should un-indent the current line
559
+ if any(keyword in stripped_line for keyword in unindent_keywords):
560
+ # Special case for 'else': it should align with its 'if'
561
+ if 'else' in stripped_line:
562
+ # Decrease indentation for 'else' and its following lines
563
+ indentation = ' ' * (indent_level -1)
564
+ formatted_lines.append(indentation + stripped_line)
565
+ continue
566
+
567
+ # For 'end', decrease the level before formatting
568
+ indent_level = max(0, indent_level - 1)
569
+
570
+ indentation = ' ' * indent_level
571
+ formatted_lines.append(indentation + stripped_line)
572
+
573
+ # Check for keywords that should indent the next line
574
+ if any(keyword in stripped_line for keyword in indent_keywords):
575
+ # 'else' both un-indents and indents, so the level remains the same for the next block
576
+ if 'else' not in stripped_line:
577
+ indent_level += 1
578
+
579
+ return '\n'.join(formatted_lines)
580
+
581
 
582
  # Node 1: Logic updating if any issue here
583
  def pseudo_generator_node(state: GameState):
 
651
 
652
  3. **Pseudo‑code formatting**:
653
  - Represent each block or nested block on its own line.
654
+ - **Indent nested blocks by 4 spaces under their parent (`forever`, `if`, etc.).This is a critical requirement.**
655
  - No comments or explanatory text—just the block sequence.
656
  - a natural language breakdown of each step taken after the event, formatted as a multi-line string representing pseudo-code. Ensure clarity and granularity—each described action should map closely to a Scratch block or tight sequence.
657
 
 
662
 
663
  5. **Examples for reference**:
664
  **Correct** pattern for a simple start script:
665
+ ```
666
+ when green flag clicked
667
+ switch backdrop to [blue sky v]
668
+ set [score v] to (0)
669
+ show variable [score v]
670
+ broadcast [Game Start v]
671
+ end
672
+ ```
673
  **Correct** pattern for updating the high score variable handling:
674
+ ```
675
+ when I receive [Game Over v]
676
+ if <((score)) > (([High Score v]))> then
677
+ set [High Score v] to ([score v])
678
+ end
679
+ switch backdrop to [Game Over v]
680
+ end
681
+ ```
682
  **Correct** pattern for level up and increase difficulty use:
683
+ ```
684
+ when I receive [Level Up v]
685
+ change [level v] by (1)
686
+ set [ballSpeed v] to ((([ballSpeed v]) * (1.1)))
687
+ end
688
+ ```
689
  **Correct** pattern for jumping mechanics use:
690
+ ```
691
+ when [space v] key pressed
692
+ if <((y position)) = (-100)> then
693
+ repeat (5)
694
+ change y by (100)
695
+ wait (0.1) seconds
696
+ change y by (-100)
697
+ wait (0.1) seconds
698
+ end
699
+ end
700
+ end
701
+ ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  **Correct** pattern for continuos moving objects use:
703
+ ```
704
+ when green flag clicked
705
+ go to x: (240) y: (-100)
706
+ set [speed v] to (-5)
707
+ show variable [speed v]
708
+ forever
709
+ change x by ([speed v])
710
+ if <((x position)) < (-240)> then
711
+ go to x: (240) y: (-100)
712
+ end
713
+ end
714
+ end
715
+ ```
716
  6. **Donot** add any explaination of logic or comments to justify or explain just put the logic content in the json.
717
  7. **Output**:
718
  Return **only** a JSON object, using double quotes everywhere:
 
874
  (([ballSpeed v]) * (1.1))
875
  ```
876
  - **Every hat block script must end** with a final `end` on its own line.
877
+ - **Indent nested blocks by 4 spaces under their parent (`forever`, `if`, etc.).This is a critical requirement.**
878
  3. **Opcode Lists**: include relevant Scratch opcodes grouped under `motion`, `control`, `operator`, `sensing`, `looks`, `sounds`, `events`, and `data`. List only the non-empty categories. Use exact opcodes.
879
  4. Few Example of content of logics inside for a specific plan as scratch pseudo-code:
880
  - example 1[continues moving objects]:
881
  ```
882
  when green flag clicked
883
+ go to x: (240) y: (-100)
884
+ set [speed v] to (-5)
885
+ show variable [speed v]
886
+ forever
887
+ change x by ([speed v])
888
+ if <((x position)) < (-240)> then
889
+ go to x: (240) y: (-100)
890
+ end
891
+ end
892
  end
893
  ```
894
  - example 2[jumping script of an plan]:
895
  ```
896
  when [space v] key pressed
897
+ if <((y position)) = (-100)> then
898
+ repeat (5)
899
+ change y by (100)
900
+ wait (0.1) seconds
901
+ change y by (-100)
902
+ wait (0.1) seconds
903
+ end
904
+ end
905
  end
906
  ```
907
  - example 3 [pattern for level up and increase difficulty]:
908
  ```
909
  when I receive [Level Up v]
910
+ change [level v] by (1)
911
+ set [ballSpeed v] to ((([ballSpeed v]) * (1.1)))
912
  end
913
  ```
914
  5. Use target names exactly as listed in `Targets in Game`. Do NOT rename or invent new targets.
 
922
  "plans": [
923
  {{
924
  "event": "event_whenflagclicked",
925
+ "logic": "when green flag clicked\n switch backdrop to [backdrop1 v]\n set [score v] to 0\n show variable [score v]\n broadcast [Game Start v]\nend",
926
  "motion": [],
927
  "control": [],
928
  "operator": [],
 
941
  }},
942
  {{
943
  "event": "event_whenbroadcastreceived",
944
+ "logic": "when I receive [Game Over v]\n if <(score) > (High Score)> then\n set [High Score v] to (score)\n end\n switch backdrop to [HighScore v]\nend",
945
  "motion": [],
946
  "control": [
947
  "control_if"
 
966
  "plans": [
967
  {{
968
  "event": "event_whenflagclicked",
969
+ "logic": "when green flag clicked\n go to x: 240 y: -100\nend",
970
  "motion": [
971
  "motion_gotoxy"
972
  ],
 
980
  }},
981
  {{
982
  "event": "event_whenkeypressed",
983
+ "logic": "when [space v] key pressed\n repeat (10)\n change y by (20)\n wait (0.1) seconds\n change y by (-20)\n end\nend",
984
  "motion": [
985
  "motion_changeyby"
986
  ],
 
1002
  "plans": [
1003
  {{
1004
  "event": "event_whenflagclicked",
1005
+ "logic": "when green flag clicked\n go to x: 240 y: -135\n forever\n glide 2 seconds to x: -240 y: -135\n if <(x position) < -235> then\n set x to 240\n end\n if <touching [Sprite1 v]?> then\n broadcast [Game Over v]\n stop [all v]\n end\n end\nend",
1006
  "motion": [
1007
  "motion_gotoxy",
1008
  "motion_glidesecstoxy",
 
1184
  - example 1[continues moving objects]:
1185
  ```
1186
  when green flag clicked
1187
+ go to x: (240) y: (-100)
1188
+ set [speed v] to (-5)
1189
+ show variable [speed v]
1190
+ forever
1191
+ change x by ([speed v])
1192
+ if <((x position)) < (-240)> then
1193
+ go to x: (240) y: (-100)
1194
+ end
1195
+ end
1196
  end
1197
  ```
1198
  - example 2[jumping script of an plan]:
1199
  ```
1200
  when [space v] key pressed
1201
+ if <((y position)) = (-100)> then
1202
+ repeat (5)
1203
+ change y by (100)
1204
+ wait (0.1) seconds
1205
+ change y by (-100)
1206
+ wait (0.1) seconds
1207
+ end
1208
+ end
1209
  end
1210
  ```
1211
  - example 3 [pattern for level up and increase difficulty]:
1212
  ```
1213
  when I receive [Level Up v]
1214
+ change [level v] by (1)
1215
+ set [ballSpeed v] to ((([ballSpeed v]) * (1.1)))
1216
  end
1217
  ```
1218
  6. Use target names exactly as listed in `Targets in Game`. Do NOT rename or invent new targets.
 
1226
  "plans": [
1227
  {{
1228
  "event": "event_whenflagclicked",
1229
+ "logic": "when green flag clicked\n switch backdrop to [backdrop1 v]\n set [score v] to 0\n show variable [score v]\n broadcast [Game Start v]\nend",
1230
  "motion": [],
1231
  "control": [],
1232
  "operator": [],
 
1245
  }},
1246
  {{
1247
  "event": "event_whenbroadcastreceived",
1248
+ "logic": "when I receive [Game Over v]\n if <(score) > (High Score)> then\n set [High Score v] to (score)\n end\n switch backdrop to [HighScore v]\nend",
1249
  "motion": [],
1250
  "control": [
1251
  "control_if"
 
1270
  "plans": [
1271
  {{
1272
  "event": "event_whenflagclicked",
1273
+ "logic": "when green flag clicked\n go to x: 240 y: -100\nend\n",
1274
  "motion": [
1275
  "motion_gotoxy"
1276
  ],
 
1284
  }},
1285
  {{
1286
  "event": "event_whenkeypressed",
1287
+ "logic": "when [space v] key pressed\n repeat (10)\n change y by (20)\n wait (0.1) seconds\n change y by (-20)\n end\nend",
1288
  "motion": [
1289
  "motion_changeyby"
1290
  ],
 
1306
  "plans": [
1307
  {{
1308
  "event": "event_whenflagclicked",
1309
+ "logic": "when green flag clicked\n go to x: 240 y: -135\n forever\n glide 2 seconds to x: -240 y: -135\n if <(x position) < -235> then\n set x to 240\n end\n if <touching [Sprite1 v]?> then\n broadcast [Game Over v]\n stop [all v]\n end\n end\nend",
1310
  "motion": [
1311
  "motion_gotoxy",
1312
  "motion_glidesecstoxy",
 
1725
  for plan_entry in sprite_actions_data.get("plans", []):
1726
  logic_sequence = str(plan_entry["logic"])
1727
  opcode_counts = plan_entry.get("opcode_counts", {})
1728
+ refined_indent_logic = format_scratch_pseudo_code(logic_sequence)
1729
+ print(f"\n--------------------------- refined indent logic: {refined_indent_logic}-------------------------------\n")
1730
  try:
1731
+ generated_blocks = block_builder(opcode_counts, refined_indent_logic)
1732
 
1733
  # Ensure generated_blocks is a dictionary
1734
  if not isinstance(generated_blocks, dict):
 
2318
  "textToSpeechLanguage": None
2319
  }
2320
  final_project["targets"].insert(0, stage_obj)
2321
+ else:
2322
+ logger.warning("⚠️ No backdrop matched. Using default static backdrop.")
2323
+ default_backdrop_path = BACKDROP_DIR / "cd21514d0531fdffb22204e0ec5ed84a.svg"
2324
+ default_backdrop_name = "cd21514d0531fdffb22204e0ec5ed84a.svg"
2325
+
2326
+ default_backdrop_sound = BACKDROP_DIR / "83a9787d4cb6f3b7632b4ddfebf74367.wav"
2327
+ default_backdrop_sound_name = "cd21514d0531fdffb22204e0ec5ed84a.svg"
2328
+ try:
2329
+ shutil.copy2(default_backdrop_path, os.path.join(project_folder, default_backdrop_name))
2330
+ logger.info(f"✅ Default backdrop copied to project: {default_backdrop_name}")
2331
+
2332
+ shutil.copy2(default_backdrop_sound, os.path.join(project_folder, default_backdrop_sound_name))
2333
+ logger.info(f"✅ Default backdrop sound copied to project: {default_backdrop_sound_name}")
2334
+ except Exception as e:
2335
+ logger.error(f"❌ Failed to copy default backdrop: {e}")
2336
+
2337
+ stage_obj={
2338
+ "isStage": True,
2339
+ "name": "Stage",
2340
+ "objName": "Stage",
2341
+ "variables": {},
2342
+ "lists": {},
2343
+ "broadcasts": {},
2344
+ "blocks": {},
2345
+ "comments": {},
2346
+ "currentCostume": 0,
2347
+ "costumes": [
2348
+ {
2349
+ "assetId": default_backdrop_name.split(".")[0],
2350
+ "name": "defaultBackdrop",
2351
+ "md5ext": default_backdrop_name,
2352
+ "dataFormat": "png",
2353
+ "rotationCenterX": 240,
2354
+ "rotationCenterY": 180
2355
+ }
2356
+ ],
2357
+ "sounds": [
2358
+ {
2359
+ "name": "pop",
2360
+ "assetId": "83a9787d4cb6f3b7632b4ddfebf74367",
2361
+ "dataFormat": "wav",
2362
+ "format": "",
2363
+ "rate": 48000,
2364
+ "sampleCount": 1123,
2365
+ "md5ext": "83a9787d4cb6f3b7632b4ddfebf74367.wav"
2366
+ }
2367
+ ],
2368
+ "volume": 100,
2369
+ "layerOrder": 0,
2370
+ "tempo": 60,
2371
+ "videoTransparency": 50,
2372
+ "videoState": "on",
2373
+ "textToSpeechLanguage": None
2374
+ }
2375
+ final_project["targets"].insert(0, stage_obj)
2376
 
2377
  with open(project_json_path, 'w') as f:
2378
  json.dump(final_project, f, indent=2)
 
2532
 
2533
  def delay_for_tpm_node(state: GameState):
2534
  logger.info("--- Running DelayForTPMNode ---")
2535
+ time.sleep(1) # Adjust the delay as needed
2536
  logger.info("Delay completed.")
2537
  return state
2538
 
 
2551
  workflow.add_node("refined_planner", refined_planner_node) # Refines the action plan
2552
  workflow.add_node("opcode_counter", plan_opcode_counter_node)
2553
  workflow.add_node("block_builder", overall_block_builder_node_2)
2554
+ workflow.add_node("variable_initializer", variable_adder_node)
2555
 
2556
  workflow.set_entry_point("pseudo_generator")
2557
  workflow.add_edge("pseudo_generator","time_delay_1")
2558
  workflow.add_edge("time_delay_1","plan_generator")
2559
  workflow.add_edge("plan_generator","time_delay_2")
2560
+ # workflow.add_edge("time_delay_2",END)
2561
  workflow.add_edge("time_delay_2","refined_planner")
2562
  workflow.add_edge("refined_planner","time_delay_3")
2563
  workflow.add_edge("time_delay_3","opcode_counter")
2564
  workflow.add_edge("opcode_counter","block_builder")
2565
+ workflow.add_edge("block_builder",variable_initializer)
2566
+ workflow.add_edge("variable_initializer", END)
2567
  app_graph = workflow.compile()
2568
 
2569
  # ============== Helper function to Upscale an Image ============== #