Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import ast | |
| import base64 | |
| import streamlit.components.v1 as components | |
| from transformers import pipeline | |
| from gtts import gTTS | |
| import qrcode | |
| from io import BytesIO | |
| st.set_page_config(page_title="AR/VR Code Visualizer", layout="wide") | |
| st.title("π AR/VR Code Visualizer with Interaction, Narration, and AR View") | |
| def load_model(): | |
| return pipeline("summarization", model="philschmid/bart-large-cnn-samsum") | |
| summarizer = load_model() | |
| st.subheader("π Write or Paste Your Python Code") | |
| code = st.text_area("Enter your Python code here", height=300) | |
| if code.strip(): | |
| st.code(code, language="python") | |
| # AST parsing to get function call relationships | |
| tree = ast.parse(code) | |
| class FunctionCallVisitor(ast.NodeVisitor): | |
| def __init__(self): | |
| self.calls = {} | |
| def visit_FunctionDef(self, node): | |
| caller = node.name | |
| self.calls[caller] = [] | |
| for child in ast.walk(node): | |
| if isinstance(child, ast.Call) and isinstance(child.func, ast.Name): | |
| self.calls[caller].append(child.func.id) | |
| self.generic_visit(node) | |
| visitor = FunctionCallVisitor() | |
| visitor.visit(tree) | |
| call_graph = visitor.calls | |
| st.subheader("π Function Calls") | |
| for fn, callees in call_graph.items(): | |
| st.write(f"πΉ `{fn}` calls: {', '.join(callees) if callees else 'None'}") | |
| # AI summary | |
| prompt = f"Explain this call graph structure: {call_graph}" | |
| summary = summarizer(prompt, max_length=60, min_length=15, do_sample=False) | |
| summary_text = summary[0]['summary_text'] | |
| st.success(summary_text) | |
| # Voice narration | |
| st.subheader("π Voice Narration") | |
| tts = gTTS(text=summary_text) | |
| tts.save("summary.mp3") | |
| st.audio("summary.mp3", format="audio/mp3") | |
| # A-Frame 3D HTML generator | |
| def generate_aframe(call_graph): | |
| function_data = { | |
| "functions": [], | |
| "relationships": [] | |
| } | |
| function_positions = {} | |
| spacing = 3 | |
| for i, fn in enumerate(call_graph): | |
| x = i * spacing | |
| function_positions[fn] = (x, 1, -3) | |
| function_data["functions"].append({"name": fn, "position": [x, 1, -3]}) | |
| for caller, callees in call_graph.items(): | |
| for callee in callees: | |
| if callee in function_positions: | |
| x1, y1, z1 = function_positions[caller] | |
| x2, y2, z2 = function_positions[callee] | |
| function_data["relationships"].append({"start": [x1, y1, z1], "end": [x2, y2, z2]}) | |
| js = f""" | |
| <script> | |
| const functionData = {str(function_data).replace("'", '"')}; | |
| function say(text) {{ | |
| const utter = new SpeechSynthesisUtterance(text); | |
| speechSynthesis.speak(utter); | |
| }} | |
| document.addEventListener('DOMContentLoaded', () => {{ | |
| functionData.functions.forEach(function(fn) {{ | |
| const box = document.createElement('a-box'); | |
| box.setAttribute('position', fn.position.join(' ')); | |
| box.setAttribute('depth', '0.5'); | |
| box.setAttribute('height', '0.5'); | |
| box.setAttribute('width', '2'); | |
| box.setAttribute('color', '#FFC65D'); | |
| box.setAttribute('class', 'clickable'); | |
| box.setAttribute('event-set__enter', '_event: mouseenter; color: #00CED1'); | |
| box.setAttribute('event-set__leave', '_event: mouseleave; color: #FFC65D'); | |
| box.setAttribute('onclick', 'say(\"' + fn.name + '\")'); | |
| document.querySelector('a-scene').appendChild(box); | |
| const text = document.createElement('a-text'); | |
| text.setAttribute('value', fn.name); | |
| text.setAttribute('position', `${{fn.position[0]}} ${{fn.position[1] + 1}} ${{fn.position[2]}}`); | |
| text.setAttribute('align', 'center'); | |
| text.setAttribute('color', '#000'); | |
| document.querySelector('a-scene').appendChild(text); | |
| }}); | |
| functionData.relationships.forEach(function(rel) {{ | |
| const el = document.createElement('a-entity'); | |
| el.setAttribute('line', `start: ${{rel.start.join(' ')}}; end: ${{rel.end.join(' ')}}; color: red`); | |
| document.querySelector('a-scene').appendChild(el); | |
| }}); | |
| }}); | |
| </script> | |
| """ | |
| html = f""" | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script> | |
| <script src="https://cdn.jsdelivr.net/gh/donmccurdy/[email protected]/dist/aframe-extras.min.js"></script> | |
| <script src="https://unpkg.com/[email protected]/dist/aframe-screenshot-component.min.js"></script> | |
| {js} | |
| </head> | |
| <body> | |
| <a-scene screenshot> | |
| <a-entity position="0 1.6 3"> | |
| <a-camera wasd-controls-enabled="true" look-controls-enabled="true"></a-camera> | |
| </a-entity> | |
| <a-light type="ambient" color="#FFF"></a-light> | |
| <a-plane rotation="-90 0 0" width="40" height="40" color="#7BC8A4"></a-plane> | |
| </a-scene> | |
| </body> | |
| </html> | |
| """ | |
| return html | |
| aframe_html = generate_aframe(call_graph) | |
| b64 = base64.b64encode(aframe_html.encode()).decode() | |
| data_url = f"data:text/html;base64,{b64}" | |
| st.subheader("π Interactive 3D Function Visualizer") | |
| components.iframe(data_url, height=600) | |
| # QR Code | |
| st.subheader("π± AR View on Mobile") | |
| qr = qrcode.QRCode(version=1, box_size=10, border=5) | |
| space_url = "https://huggingface.co/spaces/your-username/your-space-name" # Replace this | |
| qr.add_data(space_url) | |
| qr.make(fit=True) | |
| img = qr.make_image(fill_color="black", back_color="white") | |
| img_byte_arr = BytesIO() | |
| img.save(img_byte_arr, format='PNG') | |
| img_bytes = img_byte_arr.getvalue() | |
| st.image(img_bytes, caption="Scan to view in AR on mobile") | |
| else: | |
| st.info("Write some Python code above to visualize, narrate, and explore it in 3D/AR.") | |