sunbal7 commited on
Commit
2d70a3f
·
verified ·
1 Parent(s): 6cb6b14

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +408 -152
app.py CHANGED
@@ -1,16 +1,16 @@
1
- # app.py - Hugging Face Compatible Version
2
  import streamlit as st
3
- import requests
4
- import json
5
  import time
6
  import base64
7
  import random
 
 
 
 
 
8
  from PIL import Image
9
  import io
10
- import matplotlib.pyplot as plt
11
- import matplotlib.animation as animation
12
- from matplotlib.animation import FuncAnimation
13
- import numpy as np
14
 
15
  # Configure Streamlit page
16
  st.set_page_config(
@@ -113,6 +113,23 @@ st.markdown("""
113
  flex-wrap: wrap;
114
  }
115
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  </style>
117
  """, unsafe_allow_html=True)
118
 
@@ -155,15 +172,270 @@ CONCEPTS = {
155
  }
156
  }
157
 
158
- # Free AI models via Hugging Face Inference API
159
- HF_API_URL = "https://api-inference.huggingface.co/models/"
160
- MODELS = {
161
- "codegen": "Salesforce/codegen-350M-mono",
162
- "story": "gpt2"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  }
164
 
165
  def analyze_story(story):
166
- """Analyze story using simple NLP and identify programming concepts"""
167
  story_lower = story.lower()
168
  detected_concepts = []
169
 
@@ -190,152 +462,109 @@ def analyze_story(story):
190
  return list(set(detected_concepts))
191
 
192
  def generate_animation_code(story, concepts):
193
- """Generate Python animation code using free Hugging Face model"""
194
  try:
195
- # For Hugging Face Spaces, we'll use a simplified approach
196
- # since we can't run complex AI models for free
197
-
198
- # Build a template-based code generator
199
- characters = ["rabbit", "dragon", "cat", "dog", "knight", "wizard", "scientist", "pirate"]
200
- actions = ["hop", "run", "fly", "jump", "cast", "collect", "change", "grow"]
201
-
202
- character = random.choice(characters)
203
- action = random.choice(actions)
204
- count = random.randint(2, 5)
205
 
 
206
  concept = concepts[0] if concepts else "loop"
207
 
 
 
 
 
208
  if concept == "loop":
209
- code = f"""# {story}
210
- import matplotlib.pyplot as plt
211
- import matplotlib.animation as animation
212
- import numpy as np
213
-
214
- fig, ax = plt.subplots(figsize=(8, 6))
215
- ax.set_xlim(0, 10)
216
- ax.set_ylim(0, 10)
217
- ax.set_title('{" ".join(story.split()[:5])}...')
218
- ax.set_facecolor('#f0f8ff')
219
-
220
- {character}_x = [2]
221
- {character}_y = [2]
222
- {character}_dot, = ax.plot({character}_x, {character}_y, 'o', markersize=20, color='orange')
223
-
224
- carrot_x = [8]
225
- carrot_y = [8]
226
- carrot_dot, = ax.plot(carrot_x, carrot_y, 'o', markersize=15, color='orange')
227
-
228
- def animate(frame):
229
- # This is a loop that runs {count} times
230
- if frame < {count}:
231
- # Move the {character} closer to the target
232
- new_x = {character}_x[-1] + 1.5
233
- new_y = {character}_y[-1] + 1.5
234
- {character}_x.append(new_x)
235
- {character}_y.append(new_y)
236
- {character}_dot.set_data({character}_x[-1], {character}_y[-1])
237
-
238
- return {character}_dot, carrot_dot
239
-
240
- ani = animation.FuncAnimation(fig, animate, frames={count+1}, interval=1000)
241
- plt.grid(True, linestyle='--', alpha=0.7)
242
- plt.show()
243
- """
244
  elif concept == "conditional":
245
- code = f"""# {story}
246
- import matplotlib.pyplot as plt
247
- import numpy as np
248
-
249
- fig, ax = plt.subplots(figsize=(8, 6))
250
- ax.set_xlim(0, 10)
251
- ax.set_ylim(0, 10)
252
- ax.set_title('{" ".join(story.split()[:5])}...')
253
- ax.set_facecolor('#f0f8ff')
254
-
255
- # This variable stores our condition
256
- is_unlocked = {'True' if random.choice([True, False]) else 'False'}
257
-
258
- # Draw treasure chest
259
- chest = plt.Rectangle((4, 4), 2, 2, fill=True, color='brown')
260
- ax.add_patch(chest)
261
-
262
- # Draw lock if not unlocked
263
- if not is_unlocked:
264
- lock = plt.Rectangle((5, 6), 0.5, 0.8, fill=True, color='gray')
265
- ax.add_patch(lock)
266
- ax.text(5, 3, 'Locked! Find the key', fontsize=12, ha='center')
267
- else:
268
- # Show open chest with treasure
269
- chest.set_fill(False)
270
- chest.set_edgecolor('brown')
271
- chest.set_linestyle('--')
272
- ax.text(5, 5, '$$$', fontsize=20, ha='center')
273
- ax.text(5, 3, 'Treasure Acquired!', fontsize=12, ha='center')
274
-
275
- plt.grid(True, linestyle='--', alpha=0.7)
276
- plt.show()
277
- """
278
  else:
279
- code = f"""# {story}
280
- import matplotlib.pyplot as plt
281
- import numpy as np
282
-
283
- fig, ax = plt.subplots(figsize=(8, 6))
284
- ax.set_xlim(0, 10)
285
- ax.set_ylim(0, 10)
286
- ax.set_title('{" ".join(story.split()[:5])}...')
287
- ax.set_facecolor('#f0f8ff')
288
-
289
- # Draw the scene
290
- ax.text(5, 8, '✨ Your Story ✨', fontsize=20, ha='center')
291
- ax.text(5, 7, f'"{story[:50]}{"..." if len(story) > 50 else ""}"',
292
- fontsize=14, ha='center', wrap=True)
293
-
294
- # Draw coding concept icons
295
- y_pos = 5
296
- for concept in {concepts}:
297
- details = {CONCEPTS}[concept]
298
- ax.text(2, y_pos, details['emoji'], fontsize=30, ha='center')
299
- ax.text(5, y_pos, details['name'], fontsize=16, ha='left')
300
- y_pos -= 1
301
-
302
- ax.text(5, 2, 'Generated with Python!', fontsize=14, ha='center', style='italic')
303
- plt.grid(True, linestyle='--', alpha=0.7)
304
- plt.show()
305
- """
306
 
307
  return code
308
  except Exception as e:
309
  return f"# Error generating code\nprint('Could not generate code: {str(e)}')"
310
 
311
- def create_matplotlib_animation(code):
312
- """Create an animation using matplotlib"""
313
  try:
314
- # Create a namespace to execute the code
315
- namespace = {}
316
- exec(code, namespace)
 
317
 
318
- # Get the figure from the executed code
319
- fig = plt.gcf()
320
 
321
- # Create a BytesIO object to save the animation
322
- buf = io.BytesIO()
323
- fig.savefig(buf, format='png')
324
- buf.seek(0)
325
- image = Image.open(buf)
326
 
327
- return image
328
  except Exception as e:
329
  st.error(f"Animation error: {str(e)}")
330
  return None
331
 
332
- def generate_story_image(story):
333
- """Generate a story image using a free API"""
334
  try:
335
- # For Hugging Face deployment, we'll use placeholders
336
- # In a real deployment, you could use Hugging Face's diffusion models
 
 
337
 
338
- # Create a simple image with text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  fig, ax = plt.subplots(figsize=(10, 6))
340
  ax.set_facecolor('#f0f8ff')
341
  ax.set_xlim(0, 10)
@@ -396,8 +625,10 @@ def main():
396
  st.session_state.animation_code = ""
397
  if 'active_tab' not in st.session_state:
398
  st.session_state.active_tab = "story"
399
- if 'animation_image' not in st.session_state:
400
- st.session_state.animation_image = None
 
 
401
 
402
  # Create tabs
403
  tabs = st.empty()
@@ -419,7 +650,8 @@ def main():
419
  st.session_state.story = ""
420
  st.session_state.concepts = []
421
  st.session_state.animation_code = ""
422
- st.session_state.animation_image = None
 
423
  st.session_state.active_tab = "story"
424
 
425
  # Story creation tab
@@ -449,13 +681,22 @@ def main():
449
  story, st.session_state.concepts
450
  )
451
 
452
- with st.spinner("🎨 Creating your animation..."):
453
- st.session_state.animation_image = create_matplotlib_animation(
454
- st.session_state.animation_code
455
- )
 
 
 
 
 
 
 
 
 
456
 
457
  st.session_state.active_tab = "animation"
458
- st.experimental_rerun()
459
 
460
  # Show examples
461
  st.subheader("✨ Story Examples")
@@ -468,26 +709,41 @@ def main():
468
  st.code('"If it rains, the cat stays inside, else it goes out"', language="text")
469
  with col3:
470
  st.caption("Function Example")
471
- st.code('"A wizard casts a spell to make flowers grow"', language="text")
472
 
473
  # Animation tab
474
  elif st.session_state.active_tab == "animation":
475
  st.header("🎬 Your Story Animation")
476
 
477
- if not st.session_state.animation_image:
478
  st.warning("Please create a story first!")
479
  st.session_state.active_tab = "story"
480
- st.experimental_rerun()
481
 
482
  # Display animation
483
- st.image(st.session_state.animation_image, use_column_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
 
485
  st.success("✨ Animation created successfully!")
486
  st.caption("This animation was generated with Python code based on your story!")
487
 
488
  if st.button("Reveal Coding Secrets!", use_container_width=True):
489
  st.session_state.active_tab = "concepts"
490
- st.experimental_rerun()
491
 
492
  # Concepts tab
493
  elif st.session_state.active_tab == "concepts":
@@ -513,7 +769,7 @@ def main():
513
 
514
  if st.button("See the Magic Code!", use_container_width=True):
515
  st.session_state.active_tab = "code"
516
- st.experimental_rerun()
517
 
518
  # Code tab
519
  elif st.session_state.active_tab == "code":
@@ -539,7 +795,7 @@ def main():
539
  if st.button("Create Another Story!", use_container_width=True):
540
  st.session_state.active_tab = "story"
541
  st.session_state.story = ""
542
- st.experimental_rerun()
543
 
544
  if __name__ == "__main__":
545
  main()
 
 
1
  import streamlit as st
2
+ import os
 
3
  import time
4
  import base64
5
  import random
6
+ import tempfile
7
+ import subprocess
8
+ import numpy as np
9
+ import pygame
10
+ import matplotlib.pyplot as plt
11
  from PIL import Image
12
  import io
13
+ from manim import *
 
 
 
14
 
15
  # Configure Streamlit page
16
  st.set_page_config(
 
113
  flex-wrap: wrap;
114
  }
115
  }
116
+
117
+ .animation-container {
118
+ background-color: #1a1a2e;
119
+ border-radius: 15px;
120
+ padding: 20px;
121
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
122
+ margin-bottom: 25px;
123
+ position: relative;
124
+ overflow: hidden;
125
+ }
126
+
127
+ .animation-canvas {
128
+ border-radius: 10px;
129
+ overflow: hidden;
130
+ margin: 0 auto;
131
+ display: block;
132
+ }
133
  </style>
134
  """, unsafe_allow_html=True)
135
 
 
172
  }
173
  }
174
 
175
+ # Character database
176
+ CHARACTERS = {
177
+ "rabbit": {"color": (255, 150, 150), "speed": 5, "size": 30},
178
+ "dragon": {"color": (255, 100, 100), "speed": 3, "size": 60},
179
+ "cat": {"color": (200, 150, 255), "speed": 6, "size": 25},
180
+ "dog": {"color": (255, 200, 150), "speed": 7, "size": 35},
181
+ "knight": {"color": (150, 200, 255), "speed": 4, "size": 40},
182
+ "wizard": {"color": (200, 255, 150), "speed": 4, "size": 35},
183
+ "scientist": {"color": (150, 255, 200), "speed": 5, "size": 30},
184
+ "pirate": {"color": (255, 255, 150), "speed": 5, "size": 40}
185
+ }
186
+
187
+ # Animation templates
188
+ ANIMATION_TEMPLATES = {
189
+ "loop": {
190
+ "pygame": """
191
+ import pygame
192
+ import sys
193
+ import math
194
+
195
+ # Initialize pygame
196
+ pygame.init()
197
+
198
+ # Screen setup
199
+ WIDTH, HEIGHT = 800, 600
200
+ screen = pygame.display.set_mode((WIDTH, HEIGHT))
201
+ pygame.display.set_caption("Your Story Animation")
202
+
203
+ # Colors
204
+ BACKGROUND = (25, 25, 50)
205
+ GROUND = (40, 100, 40)
206
+ SUN = (255, 255, 200)
207
+
208
+ # Character setup
209
+ character = "{character}"
210
+ char_color = {char_color}
211
+ char_size = {char_size}
212
+ char_x = 100
213
+ char_y = HEIGHT - 100
214
+ char_speed = {char_speed}
215
+
216
+ # Target setup
217
+ target_x = 700
218
+ target_y = HEIGHT - 100
219
+ target_reached = False
220
+ hops = 0
221
+
222
+ # Animation clock
223
+ clock = pygame.time.Clock()
224
+ frames = []
225
+
226
+ # Main animation loop
227
+ for frame in range(120):
228
+ for event in pygame.event.get():
229
+ if event.type == pygame.QUIT:
230
+ pygame.quit()
231
+ sys.exit()
232
+
233
+ # Clear screen
234
+ screen.fill(BACKGROUND)
235
+
236
+ # Draw ground
237
+ pygame.draw.rect(screen, GROUND, (0, HEIGHT - 50, WIDTH, 50))
238
+
239
+ # Draw sun
240
+ pygame.draw.circle(screen, SUN, (700, 100), 50)
241
+
242
+ # Draw target
243
+ pygame.draw.circle(screen, (255, 200, 100), (target_x, target_y), 30)
244
+ pygame.draw.circle(screen, (255, 150, 50), (target_x, target_y), 20)
245
+ pygame.draw.circle(screen, (255, 100, 0), (target_x, target_y), 10)
246
+
247
+ # Move character
248
+ if not target_reached:
249
+ char_x += char_speed
250
+ # Hop animation
251
+ hop_height = 50 * math.sin(frame * 0.2)
252
+ char_y = HEIGHT - 100 - abs(hop_height)
253
+
254
+ # Check if target reached
255
+ if char_x >= target_x - 40:
256
+ hops += 1
257
+ char_x = 100
258
+ if hops >= {count}:
259
+ target_reached = True
260
+
261
+ # Draw character
262
+ pygame.draw.circle(screen, char_color, (int(char_x), int(char_y)), char_size)
263
+
264
+ # Draw eyes
265
+ pygame.draw.circle(screen, (255, 255, 255), (int(char_x + 10), int(char_y - 5)), 8)
266
+ pygame.draw.circle(screen, (0, 0, 0), (int(char_x + 10), int(char_y - 5)), 4)
267
+
268
+ # Draw hop counter
269
+ font = pygame.font.SysFont(None, 36)
270
+ text = font.render(f"Hops: {{hops}}/{{count}}", True, (255, 255, 255))
271
+ screen.blit(text, (20, 20))
272
+
273
+ # Capture frame
274
+ frames.append(pygame.surfarray.array3d(screen).swapaxes(0, 1))
275
+
276
+ pygame.display.flip()
277
+ clock.tick(30)
278
+
279
+ # Save animation as GIF
280
+ import imageio
281
+ imageio.mimsave('animation.gif', frames, fps=30)
282
+ """
283
+ },
284
+ "conditional": {
285
+ "pygame": """
286
+ import pygame
287
+ import sys
288
+
289
+ # Initialize pygame
290
+ pygame.init()
291
+
292
+ # Screen setup
293
+ WIDTH, HEIGHT = 800, 600
294
+ screen = pygame.display.set_mode((WIDTH, HEIGHT))
295
+ pygame.display.set_caption("Your Story Animation")
296
+
297
+ # Colors
298
+ BACKGROUND = (25, 25, 50)
299
+ GROUND = (40, 100, 40)
300
+ CHEST_COLOR = (139, 69, 19)
301
+ LOCK_COLOR = (192, 192, 192)
302
+ TREASURE_COLOR = (255, 215, 0)
303
+
304
+ # Knight setup
305
+ knight_x = 100
306
+ knight_y = HEIGHT - 100
307
+ knight_speed = 4
308
+ knight_size = 40
309
+ knight_color = (100, 150, 255)
310
+
311
+ # Chest setup
312
+ chest_x = 600
313
+ chest_y = HEIGHT - 100
314
+ chest_width = 80
315
+ chest_height = 50
316
+ is_unlocked = {condition}
317
+
318
+ # Animation clock
319
+ clock = pygame.time.Clock()
320
+ frames = []
321
+
322
+ # Main animation loop
323
+ for frame in range(180):
324
+ for event in pygame.event.get():
325
+ if event.type == pygame.QUIT:
326
+ pygame.quit()
327
+ sys.exit()
328
+
329
+ # Clear screen
330
+ screen.fill(BACKGROUND)
331
+
332
+ # Draw ground
333
+ pygame.draw.rect(screen, GROUND, (0, HEIGHT - 50, WIDTH, 50))
334
+
335
+ # Draw chest
336
+ pygame.draw.rect(screen, CHEST_COLOR, (chest_x, chest_y, chest_width, chest_height))
337
+ pygame.draw.rect(screen, (101, 67, 33), (chest_x, chest_y, chest_width, 20))
338
+
339
+ # Draw lock or treasure
340
+ if not is_unlocked:
341
+ pygame.draw.rect(screen, LOCK_COLOR, (chest_x + chest_width//2 - 10, chest_y - 15, 20, 15))
342
+ pygame.draw.circle(screen, LOCK_COLOR, (chest_x + chest_width//2, chest_y - 15), 8)
343
+ else:
344
+ pygame.draw.rect(screen, (255, 223, 0), (chest_x + 10, chest_y + 10, 20, 30))
345
+ pygame.draw.rect(screen, (218, 165, 32), (chest_x + 50, chest_y + 15, 20, 20))
346
+
347
+ # Move knight
348
+ if knight_x < chest_x - 100:
349
+ knight_x += knight_speed
350
+
351
+ # Draw knight
352
+ pygame.draw.circle(screen, knight_color, (knight_x, knight_y), knight_size)
353
+ pygame.draw.rect(screen, (50, 50, 150), (knight_x - 15, knight_y - 50, 30, 50)) # Body
354
+ pygame.draw.circle(screen, (200, 200, 200), (knight_x, knight_y - 60), 15) # Head
355
+
356
+ # Draw text
357
+ font = pygame.font.SysFont(None, 36)
358
+ if is_unlocked:
359
+ text = font.render("Chest is unlocked! Treasure acquired!", True, (255, 255, 100))
360
+ else:
361
+ text = font.render("Chest is locked! Find the key!", True, (255, 100, 100))
362
+ screen.blit(text, (WIDTH//2 - text.get_width()//2, 50))
363
+
364
+ # Capture frame
365
+ frames.append(pygame.surfarray.array3d(screen).swapaxes(0, 1))
366
+
367
+ pygame.display.flip()
368
+ clock.tick(30)
369
+
370
+ # Save animation as GIF
371
+ import imageio
372
+ imageio.mimsave('animation.gif', frames, fps=30)
373
+ """
374
+ },
375
+ "function": {
376
+ "manim": """
377
+ from manim import *
378
+
379
+ class FunctionMagic(Scene):
380
+ def construct(self):
381
+ # Create wizard and flower
382
+ wizard = Circle(radius=0.5, color=BLUE, fill_opacity=1).shift(LEFT*3)
383
+ wizard_label = Text("Wizard").next_to(wizard, DOWN)
384
+
385
+ flower = VGroup(
386
+ Circle(radius=0.3, color=GREEN).shift(UP*0.3),
387
+ Circle(radius=0.2, color=YELLOW).shift(UP*0.3),
388
+ Line(UP*0.3, DOWN*1, color=GREEN)
389
+ ).shift(RIGHT*3)
390
+ flower_label = Text("Flower").next_to(flower, DOWN)
391
+
392
+ # Create spell function
393
+ func_label = Text("cast_grow_spell()", color=YELLOW).shift(UP*2)
394
+
395
+ # Animation
396
+ self.play(Create(wizard), Write(wizard_label))
397
+ self.play(Create(flower), Write(flower_label))
398
+ self.play(Write(func_label))
399
+ self.wait(1)
400
+
401
+ # Cast spell multiple times
402
+ for i in range({count}):
403
+ # Create spell effect
404
+ spell = VGroup(
405
+ Star(color=PURPLE, fill_opacity=1).scale(0.3),
406
+ MathTex("\\star", color=PURPLE).scale(1.5)
407
+ )
408
+
409
+ # Animate spell moving
410
+ self.play(
411
+ Create(spell.move_to(wizard.get_center())),
412
+ run_time=0.5
413
+ )
414
+ self.play(
415
+ spell.animate.move_to(flower.get_center()),
416
+ run_time=1
417
+ )
418
+ self.play(FadeOut(spell))
419
+
420
+ # Grow flower
421
+ self.play(
422
+ flower.animate.scale(1.2),
423
+ run_time=0.5
424
+ )
425
+ self.wait(0.5)
426
+
427
+ # Show function call
428
+ call_text = Text(f"cast_grow_spell() #{i+1}", color=GREEN).shift(DOWN*2)
429
+ self.play(Write(call_text))
430
+ self.play(FadeOut(call_text))
431
+
432
+ self.wait(2)
433
+ """
434
+ }
435
  }
436
 
437
  def analyze_story(story):
438
+ """Analyze story and identify programming concepts"""
439
  story_lower = story.lower()
440
  detected_concepts = []
441
 
 
462
  return list(set(detected_concepts))
463
 
464
  def generate_animation_code(story, concepts):
465
+ """Generate Python animation code based on story"""
466
  try:
467
+ # Choose a random character
468
+ character = random.choice(list(CHARACTERS.keys()))
469
+ char_details = CHARACTERS[character]
 
 
 
 
 
 
 
470
 
471
+ # Choose the most relevant concept
472
  concept = concepts[0] if concepts else "loop"
473
 
474
+ # Get template for the concept
475
+ template = ANIMATION_TEMPLATES.get(concept, ANIMATION_TEMPLATES["loop"])
476
+
477
+ # Fill in template parameters
478
  if concept == "loop":
479
+ # Extract count from story
480
+ count = 3
481
+ for word in story.split():
482
+ if word.isdigit():
483
+ count = min(int(word), 10)
484
+ break
485
+
486
+ code = template["pygame"].format(
487
+ character=character,
488
+ char_color=char_details["color"],
489
+ char_size=char_details["size"],
490
+ char_speed=char_details["speed"],
491
+ count=count
492
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
  elif concept == "conditional":
494
+ condition = "True" if random.random() > 0.5 else "False"
495
+ code = template["pygame"].format(condition=condition)
496
+ elif concept == "function":
497
+ count = 3
498
+ for word in story.split():
499
+ if word.isdigit():
500
+ count = min(int(word), 5)
501
+ break
502
+ code = template["manim"].format(count=count)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
  else:
504
+ # Default to loop animation
505
+ code = ANIMATION_TEMPLATES["loop"]["pygame"].format(
506
+ character=character,
507
+ char_color=char_details["color"],
508
+ char_size=char_details["size"],
509
+ char_speed=char_details["speed"],
510
+ count=3
511
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
 
513
  return code
514
  except Exception as e:
515
  return f"# Error generating code\nprint('Could not generate code: {str(e)}')"
516
 
517
+ def run_pygame_animation(code):
518
+ """Run PyGame animation code and generate GIF"""
519
  try:
520
+ # Create a temporary Python file
521
+ with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode='w') as tmpfile:
522
+ tmpfile.write(code)
523
+ tmpfile_path = tmpfile.name
524
 
525
+ # Run the animation script
526
+ subprocess.run(["python", tmpfile_path], check=True)
527
 
528
+ # Check for generated GIF
529
+ if os.path.exists("animation.gif"):
530
+ return "animation.gif"
 
 
531
 
532
+ return None
533
  except Exception as e:
534
  st.error(f"Animation error: {str(e)}")
535
  return None
536
 
537
+ def run_manim_animation(code):
538
+ """Run Manim animation code and generate video"""
539
  try:
540
+ # Create a temporary Python file
541
+ with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode='w') as tmpfile:
542
+ tmpfile.write(code)
543
+ tmpfile_path = tmpfile.name
544
 
545
+ # Run Manim render
546
+ result = subprocess.run(
547
+ ["manim", "-ql", "-o", "animation", tmpfile_path],
548
+ capture_output=True,
549
+ text=True
550
+ )
551
+
552
+ # Find the output file
553
+ output_dir = "media/videos"
554
+ if os.path.exists(output_dir):
555
+ for file in os.listdir(output_dir):
556
+ if file.startswith("animation") and file.endswith(".mp4"):
557
+ return os.path.join(output_dir, file)
558
+
559
+ return None
560
+ except Exception as e:
561
+ st.error(f"Manim error: {str(e)}")
562
+ return None
563
+
564
+ def create_story_image(story):
565
+ """Create a story image with Matplotlib"""
566
+ try:
567
+ # Create figure
568
  fig, ax = plt.subplots(figsize=(10, 6))
569
  ax.set_facecolor('#f0f8ff')
570
  ax.set_xlim(0, 10)
 
625
  st.session_state.animation_code = ""
626
  if 'active_tab' not in st.session_state:
627
  st.session_state.active_tab = "story"
628
+ if 'animation_path' not in st.session_state:
629
+ st.session_state.animation_path = None
630
+ if 'animation_type' not in st.session_state:
631
+ st.session_state.animation_type = None
632
 
633
  # Create tabs
634
  tabs = st.empty()
 
650
  st.session_state.story = ""
651
  st.session_state.concepts = []
652
  st.session_state.animation_code = ""
653
+ st.session_state.animation_path = None
654
+ st.session_state.animation_type = None
655
  st.session_state.active_tab = "story"
656
 
657
  # Story creation tab
 
681
  story, st.session_state.concepts
682
  )
683
 
684
+ # Determine animation type
685
+ if "manim" in st.session_state.animation_code:
686
+ st.session_state.animation_type = "manim"
687
+ with st.spinner("🎬 Rendering Manim animation (this may take a minute)..."):
688
+ st.session_state.animation_path = run_manim_animation(
689
+ st.session_state.animation_code
690
+ )
691
+ else:
692
+ st.session_state.animation_type = "pygame"
693
+ with st.spinner("🎬 Creating PyGame animation..."):
694
+ st.session_state.animation_path = run_pygame_animation(
695
+ st.session_state.animation_code
696
+ )
697
 
698
  st.session_state.active_tab = "animation"
699
+ st.rerun()
700
 
701
  # Show examples
702
  st.subheader("✨ Story Examples")
 
709
  st.code('"If it rains, the cat stays inside, else it goes out"', language="text")
710
  with col3:
711
  st.caption("Function Example")
712
+ st.code('"A wizard casts a spell to make flowers grow 3 times"', language="text")
713
 
714
  # Animation tab
715
  elif st.session_state.active_tab == "animation":
716
  st.header("🎬 Your Story Animation")
717
 
718
+ if not st.session_state.animation_path:
719
  st.warning("Please create a story first!")
720
  st.session_state.active_tab = "story"
721
+ st.rerun()
722
 
723
  # Display animation
724
+ st.markdown(f"""
725
+ <div class="animation-container">
726
+ <h3 style="color: white; text-align: center;">"{st.session_state.story[:60]}{'...' if len(st.session_state.story) > 60 else ''}"</h3>
727
+ </div>
728
+ """, unsafe_allow_html=True)
729
+
730
+ try:
731
+ if st.session_state.animation_type == "pygame":
732
+ st.image(st.session_state.animation_path, use_container_width=True)
733
+ elif st.session_state.animation_type == "manim":
734
+ st.video(st.session_state.animation_path)
735
+ except Exception as e:
736
+ st.error(f"Couldn't display animation: {str(e)}")
737
+ story_image = create_story_image(st.session_state.story)
738
+ if story_image:
739
+ st.image(story_image, use_container_width=True)
740
 
741
  st.success("✨ Animation created successfully!")
742
  st.caption("This animation was generated with Python code based on your story!")
743
 
744
  if st.button("Reveal Coding Secrets!", use_container_width=True):
745
  st.session_state.active_tab = "concepts"
746
+ st.rerun()
747
 
748
  # Concepts tab
749
  elif st.session_state.active_tab == "concepts":
 
769
 
770
  if st.button("See the Magic Code!", use_container_width=True):
771
  st.session_state.active_tab = "code"
772
+ st.rerun()
773
 
774
  # Code tab
775
  elif st.session_state.active_tab == "code":
 
795
  if st.button("Create Another Story!", use_container_width=True):
796
  st.session_state.active_tab = "story"
797
  st.session_state.story = ""
798
+ st.rerun()
799
 
800
  if __name__ == "__main__":
801
  main()