sunbal7 commited on
Commit
5479f95
ยท
verified ยท
1 Parent(s): bf58f35

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +216 -409
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py - Final Version with Enhanced Animations
2
  import streamlit as st
3
  import os
4
  import time
@@ -15,6 +15,10 @@ import matplotlib.pyplot as plt
15
  import requests
16
  from io import BytesIO
17
  import json
 
 
 
 
18
 
19
  # Configure Streamlit page
20
  st.set_page_config(
@@ -155,6 +159,14 @@ st.markdown("""
155
  border-radius: 10px;
156
  box-shadow: 0 8px 16px rgba(0,0,0,0.2);
157
  }
 
 
 
 
 
 
 
 
158
  </style>
159
  """, unsafe_allow_html=True)
160
 
@@ -197,143 +209,37 @@ CONCEPTS = {
197
  }
198
  }
199
 
200
- # Character database with enhanced visuals
201
- CHARACTERS = [
202
- {"name": "rabbit", "emoji": "๐Ÿฐ", "color": "#FFB6C1", "speed": 1.5},
203
- {"name": "dragon", "emoji": "๐Ÿ‰", "color": "#FF6347", "speed": 0.8},
204
- {"name": "cat", "emoji": "๐Ÿฑ", "color": "#DDA0DD", "speed": 2.0},
205
- {"name": "dog", "emoji": "๐Ÿถ", "color": "#FFD700", "speed": 2.5},
206
- {"name": "knight", "emoji": "๐Ÿคบ", "color": "#87CEEB", "speed": 1.2},
207
- {"name": "wizard", "emoji": "๐Ÿง™", "color": "#98FB98", "speed": 1.0},
208
- {"name": "scientist", "emoji": "๐Ÿ”ฌ", "color": "#20B2AA", "speed": 1.3},
209
- {"name": "pirate", "emoji": "๐Ÿดโ€โ˜ ๏ธ", "color": "#FFA500", "speed": 1.4}
210
- ]
211
-
212
- # Object database for stories
213
- STORY_OBJECTS = [
214
- {"name": "carrot", "emoji": "๐Ÿฅ•", "color": "#FF8C00"},
215
- {"name": "treasure", "emoji": "๐Ÿ’ฐ", "color": "#FFD700"},
216
- {"name": "castle", "emoji": "๐Ÿฐ", "color": "#A9A9A9"},
217
- {"name": "flower", "emoji": "๐ŸŒธ", "color": "#FF69B4"},
218
- {"name": "book", "emoji": "๐Ÿ“š", "color": "#8B4513"},
219
- {"name": "star", "emoji": "โญ", "color": "#FFFF00"},
220
- {"name": "key", "emoji": "๐Ÿ”‘", "color": "#DAA520"},
221
- {"name": "apple", "emoji": "๐ŸŽ", "color": "#FF0000"}
222
- ]
223
-
224
- # Animation templates with visual cues
225
- ANIMATION_TEMPLATES = {
226
- "loop": {
227
- "description": "Character moving to a target multiple times",
228
- "visual_cue": "๐Ÿ”„ Repeating action multiple times",
229
- "code": """
230
- # Loop Animation
231
- import matplotlib.pyplot as plt
232
- import numpy as np
233
-
234
- fig, ax = plt.subplots(figsize=(10, 6))
235
- ax.set_title('Your Story: {story}')
236
- ax.set_xlim(0, 10)
237
- ax.set_ylim(0, 10)
238
-
239
- character = ax.text(1, 5, '{emoji}', fontsize=48, color='{color}')
240
- target = ax.text(9, 5, '{target_emoji}', fontsize=48)
241
- info = ax.text(5, 8, 'Loop: Repeating {count} times',
242
- fontsize=16, ha='center', color='{concept_color}')
243
-
244
- for i in range({count}):
245
- # Update position
246
- for pos in np.linspace(1, 9, 20):
247
- character.set_position((pos, 5))
248
- plt.pause(0.05)
249
-
250
- # Show loop counter
251
- info.set_text(f'Loop: Completed {{i+1}}/{count}')
252
- plt.pause(0.2)
253
-
254
- # Return to start
255
- for pos in np.linspace(9, 1, 20):
256
- character.set_position((pos, 5))
257
- plt.pause(0.05)
258
- plt.show()
259
- """
260
- },
261
- "conditional": {
262
- "description": "Character making a decision based on a condition",
263
- "visual_cue": "โ“ Making a decision based on a condition",
264
- "code": """
265
- # Conditional Animation
266
- import matplotlib.pyplot as plt
267
- import numpy as np
268
- import random
269
-
270
- fig, ax = plt.subplots(figsize=(10, 6))
271
- ax.set_title('Your Story: {story}')
272
- ax.set_xlim(0, 10)
273
- ax.set_ylim(0, 10)
274
-
275
- character = ax.text(5, 5, '{emoji}', fontsize=48, color='{color}')
276
- condition = random.choice([True, False])
277
- info = ax.text(5, 8, 'Condition: {condition_desc}',
278
- fontsize=16, ha='center', color='{concept_color}')
279
-
280
- if condition:
281
- # Path for True condition
282
- decision = ax.text(8, 7, 'โœ… True Path', fontsize=20, color='green')
283
- path = np.linspace(5, 8, 20)
284
- else:
285
- # Path for False condition
286
- decision = ax.text(2, 7, 'โŒ False Path', fontsize=20, color='red')
287
- path = np.linspace(5, 2, 20)
288
-
289
- for pos in path:
290
- character.set_position((pos, 5))
291
- plt.pause(0.05)
292
- plt.show()
293
- """
294
- },
295
- "function": {
296
- "description": "Character performing an action multiple times",
297
- "visual_cue": "โœจ Performing action with a function",
298
- "code": """
299
- # Function Animation
300
- import matplotlib.pyplot as plt
301
- import numpy as np
302
-
303
- fig, ax = plt.subplots(figsize=(10, 6))
304
- ax.set_title('Your Story: {story}')
305
- ax.set_xlim(0, 10)
306
- ax.set_ylim(0, 10)
307
-
308
- character = ax.text(5, 5, '{emoji}', fontsize=48, color='{color}')
309
- info = ax.text(5, 8, 'Function: Performing action {count} times',
310
- fontsize=16, ha='center', color='{concept_color}')
311
-
312
- def perform_action(position):
313
- # Action animation
314
- character.set_fontsize(60)
315
- plt.pause(0.1)
316
- character.set_fontsize(48)
317
- plt.pause(0.1)
318
- # Move to new position
319
- character.set_position((position, 5))
320
-
321
- for i in range({count}):
322
- perform_action(5 + i)
323
- info.set_text(f'Function: Action {{i+1}}/{count}')
324
- plt.pause(0.3)
325
- plt.show()
326
- """
327
- }
328
- }
329
-
330
- # Animation examples for different concepts
331
  ANIMATION_EXAMPLES = {
332
  "loop": "https://i.imgur.com/7zQY1eE.gif",
333
  "conditional": "https://i.imgur.com/5X8jYAy.gif",
334
  "function": "https://i.imgur.com/9zJkQ7P.gif"
335
  }
336
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  def analyze_story(story):
338
  """Analyze story and identify programming concepts"""
339
  story_lower = story.lower()
@@ -368,172 +274,163 @@ def extract_count_from_story(story):
368
  return min(int(word), 10)
369
  return 3 # Default value
370
 
371
- def extract_story_elements(story):
372
- """Extract characters and objects from the story"""
373
- # Choose a random character
374
- character = random.choice(CHARACTERS)
375
-
376
- # Choose a random object
377
- story_object = random.choice(STORY_OBJECTS)
378
-
379
- # Try to find character in story
380
- for char in CHARACTERS:
381
- if char["name"] in story.lower():
382
- character = char
383
- break
384
-
385
- # Try to find object in story
386
- for obj in STORY_OBJECTS:
387
- if obj["name"] in story.lower():
388
- story_object = obj
389
- break
390
-
391
- return character, story_object
392
-
393
- def create_visualization(story, concepts):
394
- """Create a visualization image based on the story and concepts"""
395
  try:
396
- # Get story elements
397
- character, story_object = extract_story_elements(story)
398
- count = extract_count_from_story(story)
399
- concept = concepts[0] if concepts else "variable"
400
- concept_color = CONCEPTS[concept]["color"]
401
-
402
- # Create figure
403
- fig, ax = plt.subplots(figsize=(10, 6))
404
- ax.set_facecolor('#f0f8ff')
405
- ax.set_xlim(0, 10)
406
- ax.set_ylim(0, 10)
407
- ax.axis('off')
408
-
409
- # Add title
410
- ax.text(5, 9, 'โœจ Your Story Visualization โœจ',
411
- fontsize=20, ha='center', color='purple', fontweight='bold')
412
 
413
- # Add story text
414
- story_text = story[:80] + ('...' if len(story) > 80 else '')
415
- ax.text(5, 8, f'"{story_text}"',
416
- fontsize=14, ha='center', color='#333')
417
 
418
- # Add character
419
- ax.text(3, 5, character["emoji"],
420
- fontsize=100, ha='center', color=character["color"])
421
-
422
- # Add object
423
- ax.text(7, 5, story_object["emoji"],
424
- fontsize=100, ha='center', color=story_object["color"])
425
 
426
- # Add connection arrow
427
- ax.annotate('', xy=(7, 5), xytext=(3, 5),
428
- arrowprops=dict(arrowstyle='->', lw=3, color=concept_color))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
 
430
- # Add concept visualization
431
- concept_text = CONCEPTS[concept]["emoji"] + " " + CONCEPTS[concept]["name"]
432
- ax.text(5, 3, concept_text,
433
- fontsize=24, ha='center', color=concept_color, fontweight='bold')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
 
435
- # Add action text
436
- action = f"Action: {character['name'].title()} moves toward {story_object['name']}"
437
- ax.text(5, 2.5, action,
438
- fontsize=16, ha='center', color='#333')
439
 
440
- # Add footer
441
- ax.text(5, 1, "Created with StoryCoder",
442
- fontsize=12, ha='center', style='italic', color='gray')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
- # Save to buffer
445
- buf = io.BytesIO()
446
- plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0.5, dpi=150)
447
- buf.seek(0)
448
- plt.close()
449
- return buf
450
 
451
  except Exception as e:
452
- st.error(f"Visualization error: {str(e)}")
453
- return None
454
 
455
- def create_interactive_animation(story, concepts):
456
  """Create an interactive animation using Plotly"""
457
  try:
458
- # Get story elements
459
- character, story_object = extract_story_elements(story)
460
- count = extract_count_from_story(story)
461
- concept = concepts[0] if concepts else "variable"
462
- concept_color = CONCEPTS[concept]["color"]
463
-
464
  # Create animation data
465
  frames = []
 
 
466
  for i in range(count):
467
- # Create a path for the character
468
- path_length = 20
469
- for step in range(path_length):
470
- progress = (i * path_length + step) / (count * path_length)
471
- frames.append({
472
- "frame": i * path_length + step,
473
- "x": 3 + 4 * progress,
474
- "y": 5 + np.sin(progress * np.pi * 2) * 2, # Wave motion
475
- "size": 20 + np.sin(step * 0.3) * 10, # Pulsing effect
476
- "character": character["emoji"],
477
- "color": character["color"],
478
- "info": f"{character['name'].title()} moving to {story_object['name']}",
479
- "step": f"Action {i+1}/{count}"
480
- })
481
 
482
  df = pd.DataFrame(frames)
483
 
484
- # Create the target object (static)
485
- target_df = pd.DataFrame([{
486
- "x": 7,
487
- "y": 5,
488
- "character": story_object["emoji"],
489
- "color": story_object["color"],
490
- "size": 30,
491
- "info": f"Target: {story_object['name']}",
492
- "step": "Target"
493
- }])
494
-
495
  # Create animated scatter plot
496
  fig = px.scatter(
497
  df,
498
  x="x",
499
  y="y",
500
  animation_frame="frame",
501
- text="character",
502
  size="size",
503
  size_max=45,
504
- color_discrete_sequence=[character["color"]],
 
505
  range_x=[0, 10],
506
  range_y=[0, 10],
507
- hover_name="info",
508
- hover_data={"step": True}
509
- )
510
-
511
- # Add the target object
512
- fig.add_trace(go.Scatter(
513
- x=target_df["x"],
514
- y=target_df["y"],
515
- text=target_df["character"],
516
- mode="text",
517
- textfont=dict(size=40, color=story_object["color"]),
518
- hoverinfo="text",
519
- hovertext=target_df["info"],
520
- showlegend=False
521
- ))
522
-
523
- # Add concept indicator
524
- fig.add_annotation(
525
- x=0.5,
526
- y=1.05,
527
- xref="paper",
528
- yref="paper",
529
- text=f"{CONCEPTS[concept]['emoji']} {CONCEPTS[concept]['name']}",
530
- showarrow=False,
531
- font=dict(size=24, color=concept_color)
532
  )
533
 
534
  # Customize layout
535
  fig.update_layout(
536
- title=f'Animation: {story[:60]}{"..." if len(story) > 60 else ""}',
537
  showlegend=False,
538
  plot_bgcolor='rgba(240,248,255,1)',
539
  paper_bgcolor='rgba(240,248,255,1)',
@@ -541,20 +438,12 @@ def create_interactive_animation(story, concepts):
541
  height=600,
542
  xaxis=dict(showgrid=False, zeroline=False, visible=False),
543
  yaxis=dict(showgrid=False, zeroline=False, visible=False),
544
- updatemenus=[dict(
545
- type="buttons",
546
- buttons=[dict(
547
- label="Play",
548
- method="animate",
549
- args=[None, {"frame": {"duration": 100, "redraw": True}}]
550
- )]
551
- )]
552
  )
553
 
554
  fig.update_traces(
555
- textfont_size=40,
556
  textposition='middle center',
557
- hoverlabel=dict(bgcolor="white", font_size=16)
558
  )
559
 
560
  return fig
@@ -563,125 +452,21 @@ def create_interactive_animation(story, concepts):
563
  st.error(f"Interactive animation error: {str(e)}")
564
  return None
565
 
566
- def text_to_speech(text, filename="story_audio.mp3"):
567
- """Convert text to speech using gTTS"""
568
- try:
569
- tts = gTTS(text=text, lang='en')
570
- tts.save(filename)
571
- return filename
572
- except Exception as e:
573
- st.error(f"Audio creation error: {str(e)}")
574
- return None
575
-
576
- def autoplay_audio(file_path):
577
- """Autoplay audio in Streamlit"""
578
- with open(file_path, "rb") as f:
579
- data = f.read()
580
- b64 = base64.b64encode(data).decode()
581
- md = f"""
582
- <audio autoplay>
583
- <source src="data:audio/mp3;base64,{b64}" type="audio/mp3">
584
- </audio>
585
- """
586
- st.markdown(md, unsafe_allow_html=True)
587
-
588
- def generate_animation_code(story, concepts):
589
- """Generate Python animation code based on story"""
590
- try:
591
- # Get story elements
592
- character, story_object = extract_story_elements(story)
593
- count = extract_count_from_story(story)
594
- concept = concepts[0] if concepts else "loop"
595
-
596
- # Get the appropriate template
597
- template = ANIMATION_TEMPLATES.get(concept, ANIMATION_TEMPLATES["loop"])
598
-
599
- # Fill in the template
600
- condition_desc = random.choice(["sunny", "raining", "dark"])
601
- code = template["code"].format(
602
- emoji=character["emoji"],
603
- color=character["color"],
604
- story=story[:80] + ('...' if len(story) > 80 else ''),
605
- count=count,
606
- condition_desc=condition_desc,
607
- target_emoji=story_object["emoji"],
608
- concept_color=CONCEPTS[concept]["color"]
609
- )
610
-
611
- return code, template["description"], template["visual_cue"]
612
-
613
- except Exception as e:
614
- return f"# Error generating code\nprint('Could not generate code: {str(e)}')", "", ""
615
-
616
- def create_story_image(story):
617
- """Create a story image with Matplotlib"""
618
- try:
619
- # Create figure
620
- fig, ax = plt.subplots(figsize=(10, 6))
621
- ax.set_facecolor('#f0f8ff')
622
- ax.set_xlim(0, 10)
623
- ax.set_ylim(0, 10)
624
- ax.axis('off')
625
-
626
- # Add title
627
- ax.text(5, 8, 'โœจ Your Story โœจ', fontsize=24,
628
- ha='center', color='purple', fontweight='bold')
629
-
630
- # Add story text (wrapped)
631
- words = story.split()
632
- lines = []
633
- current_line = []
634
-
635
- for word in words:
636
- if len(' '.join(current_line + [word])) < 60:
637
- current_line.append(word)
638
- else:
639
- lines.append(' '.join(current_line))
640
- current_line = [word]
641
-
642
- if current_line:
643
- lines.append(' '.join(current_line))
644
-
645
- for i, line in enumerate(lines):
646
- ax.text(5, 6.5 - i*0.7, line, fontsize=14, ha='center', color='#333')
647
-
648
- # Add decoration
649
- ax.text(2, 2, '๐Ÿฐ', fontsize=40, ha='center')
650
- ax.text(8, 2, '๐Ÿ‰', fontsize=40, ha='center')
651
- ax.text(5, 1, 'Created with StoryCoder', fontsize=12,
652
- ha='center', style='italic', color='gray')
653
-
654
- # Save to buffer
655
- buf = io.BytesIO()
656
- plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0.5, dpi=150)
657
- buf.seek(0)
658
- plt.close()
659
- return buf
660
-
661
- except Exception as e:
662
- st.error(f"Image generation error: {str(e)}")
663
- return None
664
-
665
- def generate_animation_preview(concept):
666
- """Get a preview GIF for the animation concept"""
667
- try:
668
- # Return a sample GIF for the concept
669
- return ANIMATION_EXAMPLES.get(concept, "https://i.imgur.com/7zQY1eE.gif")
670
- except:
671
- return "https://i.imgur.com/7zQY1eE.gif"
672
-
673
  def main():
674
  """Main application function"""
675
  st.title("๐Ÿง™โ€โ™‚๏ธ StoryCoder - Learn Python Through Stories!")
676
  st.subheader("Turn your story into an animation and discover coding secrets!")
677
 
 
 
 
678
  # Initialize session state
679
  if 'story' not in st.session_state:
680
  st.session_state.story = ""
681
  if 'concepts' not in st.session_state:
682
  st.session_state.concepts = []
683
- if 'visualization' not in st.session_state:
684
- st.session_state.visualization = None
685
  if 'interactive_animation' not in st.session_state:
686
  st.session_state.interactive_animation = None
687
  if 'animation_code' not in st.session_state:
@@ -714,7 +499,7 @@ def main():
714
  if st.button("๐Ÿ”„ Reset"):
715
  st.session_state.story = ""
716
  st.session_state.concepts = []
717
- st.session_state.visualization = None
718
  st.session_state.interactive_animation = None
719
  st.session_state.animation_code = ""
720
  st.session_state.code_description = ""
@@ -744,24 +529,29 @@ def main():
744
  with st.spinner("๐Ÿง  Analyzing your story for coding concepts..."):
745
  st.session_state.concepts = analyze_story(story)
746
 
747
- with st.spinner("๐ŸŽจ Creating your visualization..."):
748
- st.session_state.visualization = create_visualization(
749
- story, st.session_state.concepts
 
 
 
750
  )
751
-
752
  with st.spinner("๐Ÿš€ Creating interactive animation..."):
753
  st.session_state.interactive_animation = create_interactive_animation(
754
- story, st.session_state.concepts
755
  )
756
-
757
  with st.spinner("๐Ÿ’ป Generating animation code..."):
758
  st.session_state.animation_code, st.session_state.code_description, st.session_state.visual_cue = generate_animation_code(
759
- story, st.session_state.concepts
760
  )
761
 
762
  with st.spinner("๐Ÿ”Š Creating audio narration..."):
763
  audio_text = f"Your story: {story}. This demonstrates the programming concept: {st.session_state.code_description}"
764
- st.session_state.audio_file = text_to_speech(audio_text)
 
 
765
 
766
  st.session_state.active_tab = "animation"
767
  st.rerun()
@@ -772,15 +562,21 @@ def main():
772
  with col1:
773
  st.caption("Loop Example")
774
  st.code('"A dragon breathes fire 5 times at the castle"', language="text")
775
- st.image(generate_animation_preview("loop"), use_column_width=True, caption="Loop Animation Preview")
 
 
776
  with col2:
777
  st.caption("Conditional Example")
778
  st.code('"If it rains, the cat stays inside, else it goes out"', language="text")
779
- st.image(generate_animation_preview("conditional"), use_column_width=True, caption="Conditional Animation Preview")
 
 
780
  with col3:
781
  st.caption("Function Example")
782
  st.code('"A wizard casts a spell to make flowers grow"', language="text")
783
- st.image(generate_animation_preview("function"), use_column_width=True, caption="Function Animation Preview")
 
 
784
 
785
  # Animation tab
786
  elif st.session_state.active_tab == "animation":
@@ -791,30 +587,41 @@ def main():
791
  st.session_state.active_tab = "story"
792
  st.rerun()
793
 
794
- # Display visualization
795
- st.subheader("๐ŸŽจ Story Visualization")
796
- if st.session_state.visualization:
797
- st.image(st.session_state.visualization, use_container_width=True)
798
  else:
799
- st.warning("Visualization couldn't be generated. Showing story image instead.")
800
- story_img = create_story_image(st.session_state.story)
801
- if story_img:
802
- st.image(story_img, use_container_width=True)
803
 
804
  # Display interactive animation
805
- st.subheader("๐Ÿš€ Interactive Animation")
806
  if st.session_state.interactive_animation:
807
  st.plotly_chart(st.session_state.interactive_animation, use_container_width=True)
808
  else:
809
  st.info("Interactive animation preview. The real animation would run on your computer!")
810
- st.image(generate_animation_preview(st.session_state.concepts[0] if st.session_state.concepts else "loop"),
 
811
  use_container_width=True)
812
 
 
 
 
 
 
 
 
 
 
 
813
  # Play audio narration
814
  st.subheader("๐Ÿ”Š Story Narration")
815
  if st.session_state.audio_file:
816
  audio_bytes = open(st.session_state.audio_file, 'rb').read()
817
- st.audio(audio_bytes, format='audio/mp3')
818
 
819
  if st.button("โ–ถ๏ธ Play Automatically"):
820
  autoplay_audio(st.session_state.audio_file)
@@ -851,7 +658,7 @@ def main():
851
  """, unsafe_allow_html=True)
852
 
853
  # Show animation preview for the concept
854
- st.image(generate_animation_preview(concept),
855
  caption=f"{details['name']} Animation Example",
856
  use_column_width=True)
857
 
@@ -891,7 +698,7 @@ def main():
891
  # Show what the animation would look like
892
  st.subheader("๐ŸŽฌ What Your Animation Would Look Like")
893
  concept = st.session_state.concepts[0] if st.session_state.concepts else "loop"
894
- st.image(generate_animation_preview(concept),
895
  caption="This is similar to what your animation would look like",
896
  use_column_width=True)
897
  else:
 
1
+ # app.py - Final Version with AI-Powered Animations
2
  import streamlit as st
3
  import os
4
  import time
 
15
  import requests
16
  from io import BytesIO
17
  import json
18
+ import torch
19
+ from diffusers import DiffusionPipeline, StableDiffusionPipeline
20
+ import torch
21
+ from transformers import pipeline
22
 
23
  # Configure Streamlit page
24
  st.set_page_config(
 
159
  border-radius: 10px;
160
  box-shadow: 0 8px 16px rgba(0,0,0,0.2);
161
  }
162
+
163
+ .ai-animation {
164
+ border: 3px solid var(--accent);
165
+ border-radius: 15px;
166
+ padding: 15px;
167
+ background: white;
168
+ margin: 20px 0;
169
+ }
170
  </style>
171
  """, unsafe_allow_html=True)
172
 
 
209
  }
210
  }
211
 
212
+ # Pre-generated animation examples
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  ANIMATION_EXAMPLES = {
214
  "loop": "https://i.imgur.com/7zQY1eE.gif",
215
  "conditional": "https://i.imgur.com/5X8jYAy.gif",
216
  "function": "https://i.imgur.com/9zJkQ7P.gif"
217
  }
218
 
219
+ # Initialize AI models
220
+ @st.cache_resource
221
+ def load_models():
222
+ """Load AI models for animation generation"""
223
+ models = {}
224
+
225
+ try:
226
+ # Text-to-image model for scene generation
227
+ models['text_to_image'] = DiffusionPipeline.from_pretrained(
228
+ "stabilityai/stable-diffusion-2-1",
229
+ torch_dtype=torch.float16
230
+ )
231
+ except Exception as e:
232
+ st.error(f"Could not load text-to-image model: {str(e)}")
233
+ models['text_to_image'] = None
234
+
235
+ try:
236
+ # Text-to-speech model
237
+ models['text_to_speech'] = pipeline("text-to-speech", model="suno/bark-small")
238
+ except:
239
+ models['text_to_speech'] = None
240
+
241
+ return models
242
+
243
  def analyze_story(story):
244
  """Analyze story and identify programming concepts"""
245
  story_lower = story.lower()
 
274
  return min(int(word), 10)
275
  return 3 # Default value
276
 
277
+ def create_story_scene(story, concept, models):
278
+ """Create a story scene using AI text-to-image model"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  try:
280
+ # Create a prompt based on the story and concept
281
+ style = "cartoon style, bright colors, children's book illustration"
282
+ prompt = f"{story}. {CONCEPTS[concept]['name']} concept. {style}"
 
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
+ # Generate image
285
+ image = models['text_to_image'](prompt).images[0]
 
 
286
 
287
+ # Convert to bytes
288
+ buf = io.BytesIO()
289
+ image.save(buf, format='PNG')
290
+ buf.seek(0)
 
 
 
291
 
292
+ return buf
293
+
294
+ except Exception as e:
295
+ st.error(f"AI scene generation error: {str(e)}")
296
+ return None
297
+
298
+ def create_animation_preview(story, concept):
299
+ """Create an animation preview for the concept"""
300
+ try:
301
+ # Return a sample GIF for the concept
302
+ return ANIMATION_EXAMPLES.get(concept, "https://i.imgur.com/7zQY1eE.gif")
303
+ except:
304
+ return "https://i.imgur.com/7zQY1eE.gif"
305
+
306
+ def text_to_speech_custom(text, models, filename="story_audio.wav"):
307
+ """Convert text to speech using AI model"""
308
+ try:
309
+ if models['text_to_speech']:
310
+ # Generate audio
311
+ audio = models['text_to_speech'](text)
312
+
313
+ # Save to file
314
+ with open(filename, "wb") as f:
315
+ f.write(audio["audio"])
316
+
317
+ return filename
318
 
319
+ # Fallback to gTTS
320
+ tts = gTTS(text=text, lang='en')
321
+ tts.save(filename)
322
+ return filename
323
+ except Exception as e:
324
+ st.error(f"Audio creation error: {str(e)}")
325
+ return None
326
+
327
+ def autoplay_audio(file_path):
328
+ """Autoplay audio in Streamlit"""
329
+ with open(file_path, "rb") as f:
330
+ data = f.read()
331
+ b64 = base64.b64encode(data).decode()
332
+ md = f"""
333
+ <audio autoplay>
334
+ <source src="data:audio/wav;base64,{b64}" type="audio/wav">
335
+ </audio>
336
+ """
337
+ st.markdown(md, unsafe_allow_html=True)
338
+
339
+ def generate_animation_code(story, concept):
340
+ """Generate Python animation code based on story"""
341
+ try:
342
+ # Sample code based on concept
343
+ if concept == "loop":
344
+ code = f"""
345
+ # Loop Animation for: {story[:30]}...
346
+ import time
347
+
348
+ def animate_story():
349
+ actions = {extract_count_from_story(story)}
350
+
351
+ for i in range(actions):
352
+ print(f"Action {{i+1}}: {story[:20]}...")
353
+ # Animation code would go here
354
+ time.sleep(0.5)
355
 
356
+ animate_story()
357
+ """
358
+ description = "Looping through actions multiple times"
359
+ visual_cue = "Repeating actions in a loop"
360
 
361
+ elif concept == "conditional":
362
+ code = f"""
363
+ # Conditional Animation for: {story[:30]}...
364
+ import random
365
+
366
+ condition = random.choice([True, False])
367
+
368
+ if condition:
369
+ print("Condition is True: {story[:20]}...")
370
+ # True branch animation
371
+ else:
372
+ print("Condition is False: {story[:20]}...")
373
+ # False branch animation
374
+ """
375
+ description = "Making decisions based on conditions"
376
+ visual_cue = "Branching paths based on conditions"
377
+
378
+ else: # function
379
+ code = f"""
380
+ # Function Animation for: {story[:30]}...
381
+ def perform_action():
382
+ print("Performing action: {story[:20]}...")
383
+ # Action animation code
384
+
385
+ # Call the function multiple times
386
+ for _ in range({extract_count_from_story(story)}):
387
+ perform_action()
388
+ """
389
+ description = "Reusing code with functions"
390
+ visual_cue = "Calling a reusable function"
391
 
392
+ return code, description, visual_cue
 
 
 
 
 
393
 
394
  except Exception as e:
395
+ return f"# Error generating code\nprint('Could not generate code: {str(e)}')", "", ""
 
396
 
397
+ def create_interactive_animation(story, concept):
398
  """Create an interactive animation using Plotly"""
399
  try:
 
 
 
 
 
 
400
  # Create animation data
401
  frames = []
402
+ count = extract_count_from_story(story)
403
+
404
  for i in range(count):
405
+ frames.append({
406
+ "frame": i,
407
+ "x": np.random.uniform(1, 9),
408
+ "y": np.random.uniform(1, 9),
409
+ "size": np.random.uniform(20, 40),
410
+ "label": f"Action {i+1}",
411
+ "color": f"hsl({i*40}, 100%, 50%)"
412
+ })
 
 
 
 
 
 
413
 
414
  df = pd.DataFrame(frames)
415
 
 
 
 
 
 
 
 
 
 
 
 
416
  # Create animated scatter plot
417
  fig = px.scatter(
418
  df,
419
  x="x",
420
  y="y",
421
  animation_frame="frame",
422
+ text="label",
423
  size="size",
424
  size_max=45,
425
+ color="color",
426
+ color_discrete_sequence=px.colors.qualitative.Alphabet,
427
  range_x=[0, 10],
428
  range_y=[0, 10],
429
+ title=f"Interactive Animation: {story[:40]}{'...' if len(story) > 40 else ''}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  )
431
 
432
  # Customize layout
433
  fig.update_layout(
 
434
  showlegend=False,
435
  plot_bgcolor='rgba(240,248,255,1)',
436
  paper_bgcolor='rgba(240,248,255,1)',
 
438
  height=600,
439
  xaxis=dict(showgrid=False, zeroline=False, visible=False),
440
  yaxis=dict(showgrid=False, zeroline=False, visible=False),
 
 
 
 
 
 
 
 
441
  )
442
 
443
  fig.update_traces(
444
+ textfont_size=20,
445
  textposition='middle center',
446
+ marker=dict(sizemode='diameter')
447
  )
448
 
449
  return fig
 
452
  st.error(f"Interactive animation error: {str(e)}")
453
  return None
454
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
455
  def main():
456
  """Main application function"""
457
  st.title("๐Ÿง™โ€โ™‚๏ธ StoryCoder - Learn Python Through Stories!")
458
  st.subheader("Turn your story into an animation and discover coding secrets!")
459
 
460
+ # Load AI models
461
+ ai_models = load_models()
462
+
463
  # Initialize session state
464
  if 'story' not in st.session_state:
465
  st.session_state.story = ""
466
  if 'concepts' not in st.session_state:
467
  st.session_state.concepts = []
468
+ if 'story_scene' not in st.session_state:
469
+ st.session_state.story_scene = None
470
  if 'interactive_animation' not in st.session_state:
471
  st.session_state.interactive_animation = None
472
  if 'animation_code' not in st.session_state:
 
499
  if st.button("๐Ÿ”„ Reset"):
500
  st.session_state.story = ""
501
  st.session_state.concepts = []
502
+ st.session_state.story_scene = None
503
  st.session_state.interactive_animation = None
504
  st.session_state.animation_code = ""
505
  st.session_state.code_description = ""
 
529
  with st.spinner("๐Ÿง  Analyzing your story for coding concepts..."):
530
  st.session_state.concepts = analyze_story(story)
531
 
532
+ # Get the main concept
533
+ main_concept = st.session_state.concepts[0] if st.session_state.concepts else "variable"
534
+
535
+ with st.spinner("๐ŸŽจ Generating AI story scene..."):
536
+ st.session_state.story_scene = create_story_scene(
537
+ story, main_concept, ai_models
538
  )
539
+
540
  with st.spinner("๐Ÿš€ Creating interactive animation..."):
541
  st.session_state.interactive_animation = create_interactive_animation(
542
+ story, main_concept
543
  )
544
+
545
  with st.spinner("๐Ÿ’ป Generating animation code..."):
546
  st.session_state.animation_code, st.session_state.code_description, st.session_state.visual_cue = generate_animation_code(
547
+ story, main_concept
548
  )
549
 
550
  with st.spinner("๐Ÿ”Š Creating audio narration..."):
551
  audio_text = f"Your story: {story}. This demonstrates the programming concept: {st.session_state.code_description}"
552
+ st.session_state.audio_file = text_to_speech_custom(
553
+ audio_text, ai_models
554
+ )
555
 
556
  st.session_state.active_tab = "animation"
557
  st.rerun()
 
562
  with col1:
563
  st.caption("Loop Example")
564
  st.code('"A dragon breathes fire 5 times at the castle"', language="text")
565
+ st.image(create_animation_preview("", "loop"),
566
+ use_column_width=True,
567
+ caption="Loop Animation Preview")
568
  with col2:
569
  st.caption("Conditional Example")
570
  st.code('"If it rains, the cat stays inside, else it goes out"', language="text")
571
+ st.image(create_animation_preview("", "conditional"),
572
+ use_column_width=True,
573
+ caption="Conditional Animation Preview")
574
  with col3:
575
  st.caption("Function Example")
576
  st.code('"A wizard casts a spell to make flowers grow"', language="text")
577
+ st.image(create_animation_preview("", "function"),
578
+ use_column_width=True,
579
+ caption="Function Animation Preview")
580
 
581
  # Animation tab
582
  elif st.session_state.active_tab == "animation":
 
587
  st.session_state.active_tab = "story"
588
  st.rerun()
589
 
590
+ # Display AI-generated scene
591
+ st.subheader("๐Ÿ–ผ๏ธ AI-Generated Story Scene")
592
+ if st.session_state.story_scene:
593
+ st.image(st.session_state.story_scene, use_container_width=True)
594
  else:
595
+ st.warning("Scene couldn't be generated. Showing example instead.")
596
+ concept = st.session_state.concepts[0] if st.session_state.concepts else "loop"
597
+ st.image(create_animation_preview("", concept),
598
+ use_container_width=True)
599
 
600
  # Display interactive animation
601
+ st.subheader("๐ŸŽฎ Interactive Animation")
602
  if st.session_state.interactive_animation:
603
  st.plotly_chart(st.session_state.interactive_animation, use_container_width=True)
604
  else:
605
  st.info("Interactive animation preview. The real animation would run on your computer!")
606
+ concept = st.session_state.concepts[0] if st.session_state.concepts else "loop"
607
+ st.image(create_animation_preview("", concept),
608
  use_container_width=True)
609
 
610
+ # Animation concept preview
611
+ st.subheader("๐Ÿ“ฝ๏ธ Animation Concept Preview")
612
+ if st.session_state.concepts:
613
+ concept = st.session_state.concepts[0]
614
+ st.image(create_animation_preview("", concept),
615
+ caption=f"{CONCEPTS[concept]['name']} Animation Example",
616
+ use_container_width=True)
617
+ else:
618
+ st.info("Animation preview would appear here")
619
+
620
  # Play audio narration
621
  st.subheader("๐Ÿ”Š Story Narration")
622
  if st.session_state.audio_file:
623
  audio_bytes = open(st.session_state.audio_file, 'rb').read()
624
+ st.audio(audio_bytes, format='audio/wav')
625
 
626
  if st.button("โ–ถ๏ธ Play Automatically"):
627
  autoplay_audio(st.session_state.audio_file)
 
658
  """, unsafe_allow_html=True)
659
 
660
  # Show animation preview for the concept
661
+ st.image(create_animation_preview("", concept),
662
  caption=f"{details['name']} Animation Example",
663
  use_column_width=True)
664
 
 
698
  # Show what the animation would look like
699
  st.subheader("๐ŸŽฌ What Your Animation Would Look Like")
700
  concept = st.session_state.concepts[0] if st.session_state.concepts else "loop"
701
+ st.image(create_animation_preview("", concept),
702
  caption="This is similar to what your animation would look like",
703
  use_column_width=True)
704
  else: