Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from groq import Groq | |
| import os | |
| import json | |
| import datetime | |
| import copy | |
| # Ordner für lokale Projekte | |
| PROJECT_DIR = "projects" | |
| os.makedirs(PROJECT_DIR, exist_ok=True) | |
| # Aktuelles Projekt | |
| current_project = {"name": None, "code": "", "chat_history": [], "checkpoints": []} | |
| # ------------------------------ | |
| # Hilfsfunktionen | |
| # ------------------------------ | |
| def list_projects(): | |
| files = [f.replace(".json","") for f in os.listdir(PROJECT_DIR) if f.endswith(".json")] | |
| return files if files else ["Keine Projekte"] | |
| def create_checkpoint(): | |
| """Speichert aktuellen Code + Chat als Checkpoint""" | |
| global current_project | |
| checkpoint = { | |
| "timestamp": datetime.datetime.now().strftime("%Y%m%d_%H%M%S"), | |
| "code": copy.deepcopy(current_project["code"]), | |
| "chat_history": copy.deepcopy(current_project["chat_history"]) | |
| } | |
| current_project["checkpoints"].append(checkpoint) | |
| def update_checkpoint_list(): | |
| return [c["timestamp"] for c in current_project["checkpoints"]] if current_project["checkpoints"] else [] | |
| def new_project(): | |
| global current_project | |
| timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") | |
| current_project = { | |
| "name": f"Projekt_{timestamp}", | |
| "code": """<!DOCTYPE html> | |
| <html> | |
| <head><meta charset="UTF-8"><title>Neues Spiel</title></head> | |
| <body><canvas id="game"></canvas> | |
| <script> | |
| const canvas = document.getElementById('game'); | |
| const ctx = canvas.getContext('2d'); | |
| canvas.width = window.innerWidth; | |
| canvas.height = window.innerHeight; | |
| let x=50,y=50; | |
| function loop(){ctx.clearRect(0,0,canvas.width,canvas.height);ctx.fillStyle='lime';ctx.fillRect(x,y,50,50);x+=1;requestAnimationFrame(loop);} | |
| loop(); | |
| </script></body></html>""", | |
| "chat_history": [], | |
| "checkpoints": [] | |
| } | |
| create_checkpoint() | |
| return current_project["code"], "<p>Live Vorschau</p>", list_projects(), "Neues Projekt erstellt: " + current_project["name"], update_checkpoint_list() | |
| def load_project(project_name): | |
| global current_project | |
| filepath = os.path.join(PROJECT_DIR,f"{project_name}.json") | |
| if os.path.exists(filepath): | |
| with open(filepath,"r",encoding="utf-8") as f: | |
| current_project = json.load(f) | |
| html_escaped = current_project["code"].replace('"', """) | |
| iframe_html = f"<iframe srcdoc='{html_escaped}' width='100%' height='400px' style='border:none;'></iframe>" | |
| return current_project["code"], iframe_html, list_projects(), f"Projekt geladen: {project_name}", update_checkpoint_list() | |
| else: | |
| return "", "<p>Keine Vorschau</p>", list_projects(), "Projekt nicht gefunden", [] | |
| def save_project(): | |
| global current_project | |
| if not current_project["name"]: | |
| return "Kein Projekt aktiv!" | |
| filepath = os.path.join(PROJECT_DIR, f"{current_project['name']}.json") | |
| with open(filepath,"w",encoding="utf-8") as f: | |
| json.dump(current_project,f,indent=2,ensure_ascii=False) | |
| return f"Projekt gespeichert: {current_project['name']}" | |
| def save_code_local(code): | |
| global current_project | |
| current_project["code"] = code | |
| create_checkpoint() | |
| return save_project(), update_checkpoint_list() | |
| def chat_generate(api_key, model_name, user_input, current_code): | |
| global current_project | |
| if not api_key: | |
| return current_code, "<p>Keine Vorschau</p>", "Bitte API-Key eingeben!", update_checkpoint_list() | |
| try: | |
| client = Groq(api_key=api_key) | |
| system_prompt = {"role":"system","content":( | |
| "Du bist ein professioneller Game Developer und AI-Coding-Assistent. " | |
| "Bearbeite oder erweitere den gegebenen HTML5-Code, nur gültiges HTML+JS, " | |
| "Canvas-basiertes Spiel, sofort spielbar, keine Erklärungen." | |
| )} | |
| user_message = {"role":"user","content": f"Aktueller Code:\n{current_code}\n\nAnfrage:\n{user_input}"} | |
| messages = [system_prompt] + current_project["chat_history"] + [user_message] | |
| completion = client.chat.completions.create( | |
| model=model_name, | |
| messages=messages, | |
| temperature=0.8 | |
| ) | |
| model_response = completion.choices[0].message.content | |
| current_project["code"] = model_response | |
| current_project["chat_history"].append(user_message) | |
| current_project["chat_history"].append({"role":"assistant","content":model_response}) | |
| create_checkpoint() | |
| html_escaped = model_response.replace('"', """) | |
| preview_html = f"<iframe srcdoc='{html_escaped}' width='100%' height='400px' style='border:none;'></iframe>" | |
| return model_response, preview_html, "✅ KI Update fertig", update_checkpoint_list() | |
| except Exception as e: | |
| return current_code, "<p>Fehler bei der Vorschau</p>", f"Fehler: {e}", update_checkpoint_list() | |
| def load_checkpoint(checkpoint_time): | |
| for c in current_project["checkpoints"]: | |
| if c["timestamp"] == checkpoint_time: | |
| current_project["code"] = c["code"] | |
| current_project["chat_history"] = c["chat_history"] | |
| html_escaped = c["code"].replace('"', """) | |
| iframe_html = f"<iframe srcdoc='{html_escaped}' width='100%' height='400px' style='border:none;'></iframe>" | |
| return current_project["code"], iframe_html, "✅ Checkpoint geladen" | |
| return current_project["code"], "<p>Keine Vorschau</p>", "Checkpoint nicht gefunden" | |
| def delete_checkpoint(checkpoint_time): | |
| global current_project | |
| current_project["checkpoints"] = [c for c in current_project["checkpoints"] if c["timestamp"] != checkpoint_time] | |
| return update_checkpoint_list(), "✅ Checkpoint gelöscht" | |
| # ------------------------------ | |
| # Gradio UI | |
| # ------------------------------ | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# 🕹️ HTML5 Game Studio mit AI & Checkpoints") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### KI Beschreibung / Hinweise") | |
| ki_desc = gr.HTML("<p>Hier erscheinen Hinweise der KI und aktuelle Anfrage</p>") | |
| api_key_input = gr.Textbox(label="GROQ API-Key", placeholder="Hier API-Key einfügen", type="password") | |
| model_input = gr.Textbox(label="AI Modell", placeholder="Beispiel: llama3-70b-8192 oder gpt-os", value="llama3-70b-8192") | |
| user_input = gr.Textbox(label="Spielidee / Follow-up", placeholder="Beispiel: Gegner hinzufügen", lines=3) | |
| with gr.Row(): | |
| btn_new = gr.Button("🆕 New Project") | |
| btn_save_code = gr.Button("💾 Save Code") | |
| btn_ai = gr.Button("🤖 Mit AI aktualisieren") | |
| project_dropdown = gr.Dropdown(list_projects(), label="Projekt laden") | |
| btn_load = gr.Button("📂 Load Project") | |
| btn_save_project = gr.Button("💾 Save Project") | |
| gr.Markdown("### Checkpoints") | |
| checkpoint_dropdown = gr.Dropdown([], label="Checkpoint auswählen") | |
| btn_load_checkpoint = gr.Button("⬅️ Wiederherstellen") | |
| btn_delete_checkpoint = gr.Button("❌ Löschen") | |
| code_editor = gr.Code(language="html", label="HTML5 Game Code", lines=20, value="") | |
| status_output = gr.Textbox(label="Status", interactive=False) | |
| with gr.Column(scale=1): | |
| gr.Markdown("### Live Vorschau") | |
| preview_output = gr.HTML("<p>Vorschau erscheint hier</p>") | |
| # ------------------------------ | |
| # Events | |
| # ------------------------------ | |
| btn_new.click(new_project, outputs=[code_editor, preview_output, project_dropdown, status_output, checkpoint_dropdown]) | |
| btn_load.click(load_project, inputs=[project_dropdown], outputs=[code_editor, preview_output, project_dropdown, status_output, checkpoint_dropdown]) | |
| btn_save_code.click(save_code_local, inputs=[code_editor], outputs=[status_output, checkpoint_dropdown]) | |
| btn_save_project.click(save_project, outputs=[status_output]) | |
| btn_ai.click(chat_generate, inputs=[api_key_input, model_input, user_input, code_editor], outputs=[code_editor, preview_output, status_output, checkpoint_dropdown]) | |
| btn_load_checkpoint.click(load_checkpoint, inputs=[checkpoint_dropdown], outputs=[code_editor, preview_output, status_output]) | |
| btn_delete_checkpoint.click(delete_checkpoint, inputs=[checkpoint_dropdown], outputs=[checkpoint_dropdown, status_output]) | |
| demo.launch() | |