Spaces:
Running
Running
Update app.py
Browse files
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 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
**Correct** pattern for updating the high score variable handling:
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
**Correct** pattern for level up and increase difficulty use:
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
**Correct** pattern for jumping mechanics use:
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
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 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
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 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
end
|
817 |
```
|
818 |
- example 2[jumping script of an plan]:
|
819 |
```
|
820 |
when [space v] key pressed
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
|
829 |
end
|
830 |
```
|
831 |
- example 3 [pattern for level up and increase difficulty]:
|
832 |
```
|
833 |
when I receive [Level Up v]
|
834 |
-
|
835 |
-
|
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\
|
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 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
end
|
1121 |
```
|
1122 |
- example 2[jumping script of an plan]:
|
1123 |
```
|
1124 |
when [space v] key pressed
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
end
|
1134 |
```
|
1135 |
- example 3 [pattern for level up and increase difficulty]:
|
1136 |
```
|
1137 |
when I receive [Level Up v]
|
1138 |
-
|
1139 |
-
|
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\
|
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,
|
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(
|
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 |
-
|
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",
|
2434 |
-
|
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 ============== #
|