# -*- coding: utf-8 -*- """🎨 Quran Interface v8.1 — With Code-to-App Workshop ✅ Visualizing the Invisible | ✅ Live Code Compiler | ✅ Auto-UI Generator """ import gradio as gr import matplotlib.pyplot as plt import numpy as np import json, ast, re, tempfile, os from datetime import datetime # اتصال به موتور اصلی (از سلول قبل) try: orchestrator, parser, kb = get_analyzer() CORE_LOADED = True except NameError: CORE_LOADED = False print("❌ Error: core_engine.py must be run first!") # ═══════════════════════════════════════════════════════════ # ۱. گزارش‌دهی فلسفی (همان قبلی) # ═══════════════════════════════════════════════════════════ class NarrativeGenerator: @staticmethod def generate_philosophical_report(res): md = ["# 🌌 گزارش جامع تحلیل قرآنی (نسخه ۸.۰)\n"] md.append(f"**زمان:** {datetime.now().strftime('%H:%M:%S')}\n---\n") fd = res['fractal_dim'] md.append(f"## ۱. هندسه معنا\n- بُعد فراکتالی: `{fd}`\n") if fd > 1.5: md.append("> پیچیدگی ساختاری بالا (شبیه کریستال).\n") elif fd < 1.2: md.append("> سادگی و خطی بودن نسبی.\n") cb = res['cosmic_balance'] md.append(f"## ۲. ترازوی عدالت و رحمت\n- شاخص: `{cb['index']}` ({cb['state']})\n") if cb['index'] > 0.3: md.append("💡 سیطره رحمت.\n") elif cb['index'] < -0.3: md.append("💡 غلبه هشدار.\n") sd = res['semantic_drift'] md.append(f"## ۳. مسیر حرکت معنا\n- زاویه رانش: `{sd['drift_magnitude']}°`\n") if sd['drift_magnitude'] > 60: md.append("🔄 چرخش معنایی شدید.\n") elif sd['drift_magnitude'] < 15: md.append("➡️ انسجام بالا.\n") rd = res['rhetoric_density'] md.append(f"## ۴. نقشه زیبایی‌شناسی\n- میانگین تراکم: `{rd['average_density']}`\n") if rd['peak_verse']: pv = rd['peak_verse'] md.append(f"- اوج بلاغت: آیه `{pv['verse_id']}` ({', '.join(pv['features'])})\n") th = res['theology'] md.append(f"## ۵. سامانه اعتقادی\n- موضوع غالب: `{th['dominant_theme']}`\n- انسجام: `{th['coherence_score']}`\n") md.append("\n---\n## 💎 سنتز نهایی\n") summary = [] if fd > 1.3: summary.append("پیچیده") if cb['index'] > 0: summary.append("رحمت‌محور") elif cb['index'] < 0: summary.append("هشدارمحور") else: summary.append("متعادل") md.append(f"> این قطعه {', '.join(summary)} است با تمرکز بر «{th['dominant_theme']}».\n") return "\n".join(md) def create_visualizations(res): plots = {} try: # ۱. Gauge Chart idx = res['cosmic_balance']['index'] plt.figure(figsize=(6, 3), facecolor='#1a1a2e') ax = plt.subplot(111); ax.set_facecolor('#1a1a2e') theta = np.linspace(0, np.pi, 100) colors = ['#F44336' if x < -0.3 else ('#FFEB3B' if abs(x) <= 0.3 else '#4CAF50') for x in np.cos(theta)] ax.fill_between(np.cos(theta)*1.0, np.sin(theta)*1.0, np.cos(theta)*0.7, np.sin(theta)*0.7, color=colors, alpha=0.5) angle = (idx + 1) / 2 * np.pi ax.plot([0, np.cos(angle)*0.9], [0, np.sin(angle)*0.9], 'w-', linewidth=3) ax.scatter(np.cos(angle)*0.9, np.sin(angle)*0.9, c='white', s=100) ax.set_xlim(-1.2, 1.2); ax.set_ylim(-0.2, 1.2); ax.axis('off') ax.text(0, -0.1, f"Balance: {idx}", ha='center', color='white', fontsize=12, weight='bold') plt.tight_layout(); p="/tmp/v8_cosmic.png"; plt.savefig(p, dpi=100, bbox_inches='tight', facecolor='#1a1a2e'); plt.close() plots['cosmic'] = p # ۲. Heatmap Strip density_map = res['rhetoric_density']['map'] scores = [d['score'] for d in density_map] labels = [d['verse_id'] for d in density_map] plt.figure(figsize=(10, 2), facecolor='#1a1a2e') ax = plt.gca(); ax.set_facecolor('#1a1a2e') im = ax.imshow([scores], cmap='inferno', aspect='auto') ax.set_xticks(range(len(labels))); ax.set_xticklabels(labels, rotation=45, ha='right', color='white', fontsize=7) ax.set_yticks([]); ax.set_title('Rhetorical Density', color='white', fontsize=10) plt.colorbar(im, ax=ax, shrink=0.8) plt.tight_layout(); p="/tmp/v8_rhetoric.png"; plt.savefig(p, dpi=100, bbox_inches='tight', facecolor='#1a1a2e'); plt.close() plots['rhetoric'] = p # ۳. Radar topics = res['theology']['topic_distribution'] if topics: keys = list(topics.keys()); vals = list(topics.values()) plt.figure(figsize=(5, 5), facecolor='#1a1a2e') ax = plt.subplot(111, projection='polar') angles = np.linspace(0, 2*np.pi, len(keys), endpoint=False).tolist() vals += vals[:1]; angles += angles[:1] ax.plot(angles, vals, 'o-', linewidth=2, color='#FFD700') ax.fill(angles, vals, alpha=0.25, color='#FFD700') ax.set_thetagrids(np.degrees(angles[:-1]), keys, color='white') ax.grid(color='gray', linestyle='--', alpha=0.3) ax.set_title('Theological Radar', color='white', pad=20) plt.tight_layout(); p="/tmp/v8_theology.png"; plt.savefig(p, dpi=100, bbox_inches='tight', facecolor='#1a1a2e'); plt.close() plots['theology'] = p except Exception as e: log.error(f"Vis Error: {e}") return plots # ═══════════════════════════════════════════════════════════ # ۲. موتور کارگاه تبدیل کد به برنامه (Code-to-App Engine) # ═══════════════════════════════════════════════════════════ class CodeWorkshopEngine: @staticmethod def analyze_and_wrap_code(raw_code): """ ۱. کد را پارس می‌کند تا توابع را پیدا کند. ۲. یک اسکلت Gradio برای هر تابع می‌سازد. ۳. کد نهایی قابل اجرا را تولید می‌کند. """ try: tree = ast.parse(raw_code) except SyntaxError as e: return None, f"❌ خطای سینتکس در کد شما:\n{e}" functions = [] imports = set() # استخراج import ها for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: imports.add(alias.name.split('.')[0]) elif isinstance(node, ast.ImportFrom): if node.module: imports.add(node.module.split('.')[0]) # استخراج توابع if isinstance(node, ast.FunctionDef): args = [arg.arg for arg in node.args.args] returns_str = "str" # پیش‌فرض if node.returns and isinstance(node.returns, ast.Name): returns_str = node.returns.id # تشخیص نوع ورودی بر اساس نام پارامتر input_type = "textbox" if any(k in a.lower() for a in args for k in ['num', 'int', 'float']): input_type = "number" elif any(k in a.lower() for a in args for k in ['img', 'image', 'pic']): input_type = "image" functions.append({ 'name': node.name, 'args': args, 'return_type': returns_str, 'input_widget': input_type, 'source_code': ast.get_source_segment(raw_code, node) or "" }) if not functions: return None, "⚠️ هیچ تابعی (def ...) در کد یافت نشد. لطفاً حداقل یک تابع بنویسید." # ساخت کد نهایی header = "# Auto-generated by AI Studio Workshop\nimport gradio as gr\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport math\nimport random\nimport json\nimport re\nfrom datetime import datetime\n\n" body = "" ui_blocks = [] for func in functions: # افزودن تابع اصلی body += f"\n# --- Function: {func['name']} ---\n" body += func['source_code'] + "\n\n" # ساخت ویجت UI برای این تابع widgets = [] for i, arg in enumerate(func['args']): if func['input_widget'] == 'number': widgets.append(f"gr.Number(label='{arg}')") elif func['input_widget'] == 'image': widgets.append(f"gr.Image(label='{arg}')") else: widgets.append(f"gr.Textbox(label='{arg}', lines=3)") widget_list = ", ".join(widgets) if widgets else "" output_widget = "gr.Textbox(label='Output')" if func['return_type'] == 'str' else "gr.JSON(label='Result JSON')" ui_block = f""" with gr.Tab("{func['name']}"): with gr.Row(): inputs = [{widget_list}] btn_{func['name']} = gr.Button("Run {func['name']}") out_{func['name']} = {output_widget} btn_{func['name']}.click(fn={func['name']}, inputs=inputs, outputs=out_{func['name']}) """ ui_blocks.append(ui_block) footer = f""" demo = gr.Blocks(title="My Custom App") with demo: gr.Markdown("# 🛠️ My Personal Tool\\nGenerated automatically from your code.") with gr.Tabs(): {''.join(ui_blocks)} if __name__ == "__main__": demo.launch(share=True) """ final_script = header + body + footer return final_script, "✅ کد با موفقیت تجزیه و بسته‌بندی شد!" @staticmethod def execute_sandboxed(code_string): """ اجرای ایمن کد در یک محیط محدود (Sandbox-lite) """ local_env = {"__builtins__": {}} allowed_modules = {'math', 'random', 'json', 're', 'datetime', 'numpy', 'pd', 'plt'} # تزریق ماژول‌های مجاز import builtins safe_builtins = {k: getattr(builtins, k) for k in dir(builtins) if k not in ['open', 'exec', 'eval', '__import__', 'compile']} local_env['__builtins__'] = safe_builtins # ایمپورت ماژول‌های مجاز for mod_name in allowed_modules: try: exec(f"import {mod_name}", local_env) except ImportError: pass try: exec(code_string, local_env) return True, "Execution Successful", local_env except Exception as e: return False, f"Runtime Error: {str(e)}", None # ═══════════════════════════════════════════════════════════ # ۳. رابط کاربری Gradio (با تب جدید کارگاه) # ═══════════════════════════════════════════════════════════ SAMPLE_JSON = '[{"surah":1,"ayah":1,"text":"بسم الله الرحمن الرحيم"},{"surah":1,"ayah":2,"text":"الحمد لله رب العالمين"},{"surah":112,"ayah":1,"text":"قل هو الله احد"}]' EXAMPLE_CODE_FOR_WORKSHOP = ''' def fibonacci(n): """Generate Fibonacci sequence up to n terms.""" if n <= 0: return [] fib_seq = [0, 1] while len(fib_seq) < n: next_val = fib_seq[-1] + fib_seq[-2] fib_seq.append(next_val) return str(fib_seq) def calculate_area(radius): """Calculate area of circle.""" import math area = math.pi * radius ** 2 return f"Area: {area:.2f}" ''' if CORE_LOADED: workshop_engine = CodeWorkshopEngine() with gr.Blocks(title="Quran Analyzer v8.1 Ultimate") as demo: gr.Markdown(""" ### 📖 Quran Analyzer v8.1 — The Grand Unified Theory Edition ⚡ **۷ موتور تحلیلی** | 🧠 **تفسیر فلسفی** | 🏗️ **کارگاه تبدیل کد به اپلیکیشن** """) with gr.Tabs(): # --- تب ۱: تحلیل قرآن --- with gr.TabItem("📖 Quran Analysis"): with gr.Row(): with gr.Column(scale=1): inp_quran = gr.Textbox(label="📄 Input Data", value=SAMPLE_JSON, lines=12) btn_quran = gr.Button("🚀 RUN ANALYSIS", variant="primary", size="lg") with gr.Column(scale=2): stat_quran = gr.Textbox(label="📡 Status", interactive=False) narrative_quran = gr.Markdown(label="🧠 Philosophical Report", height=400) with gr.Row(): plot_cosmic = gr.Image(label="⚖️ Cosmic Balance", type="filepath") plot_theology = gr.Image(label="🕸️ Theological Radar", type="filepath") plot_rhetoric = gr.Image(label="🔥 Rhetorical Map", type="filepath") # --- تب ۲: کارگاه تبدیل کد به برنامه (جدید!) --- with gr.TabItem("🏗️ Code-to-App Workshop"): gr.Markdown(""" ### 🛠️ تبدیل خودکار کد پایتون به رابط کاربری ۱. کد پایتون خود را (حاوی توابع `def`) در کادر زیر Paste کنید. ۲. دکمه **«تبدیل و پیش‌نمایش»** را بزنید. ۳. سیستم به طور خودکار برای هر تابع، ورودی مناسب (متن، عدد، تصویر) ساخته و رابط گرافیکی می‌دهد. ۴. می‌توانید کد نهایی را دانلود کرده و روی کامپیوتر خود اجرا کنید. """) with gr.Row(): with gr.Column(scale=1): code_input = gr.Code(label="Paste Your Python Code Here", language="python", lines=15, value=EXAMPLE_CODE_FOR_WORKSHOP) convert_btn = gr.Button("🔄 Convert & Preview", variant="primary", size="lg") with gr.Column(scale=1): status_ws = gr.Textbox(label="Status", interactive=False, lines=2) generated_app_preview = gr.Code(label="Generated App Script (.py)", language="python", lines=15) download_btn = gr.DownloadButton(label="⬇️ Download Script", variant="secondary") with gr.Accordion("🧪 Live Sandbox Test (Optional)", open=False): gr.Markdown("*اجرای سریع تابع اول موجود در کد بالا برای تست عملکرد.*") test_arg_1 = gr.Textbox(label="Argument 1 (String/Number)", value="10") run_test_btn = gr.Button("▶️ Run First Function") test_output = gr.Textbox(label="Function Output", interactive=False) # --- Event Handlers for Workshop --- def handle_conversion(code_str): script, msg = workshop_engine.analyze_and_wrap_code(code_str) if script: # ذخیره موقت برای دانلود tmp_path = tempfile.mktemp(suffix=".py") with open(tmp_path, "w", encoding="utf-8") as f: f.write(script) return msg, script, tmp_path else: return msg, "", None def handle_live_test(code_str, arg_str): # تلاش برای استخراج اولین تابع try: tree = ast.parse(code_str) first_func = None for node in ast.walk(tree): if isinstance(node, ast.FunctionDef): first_func = node break if not first_func: return "❌ No function found." func_name = first_func.name # اجرای ایمن success, result_msg, env = workshop_engine.execute_sandboxed(code_str) if success and func_name in env: fn = env[func_name] # سعی در تبدیل آرگومان try: # اگر آرگومان عددی است if '.' in arg_str or arg_str.isdigit(): val = float(arg_str) if '.' in arg_str else int(arg_str) else: val = arg_str res = fn(val) return f"✅ Result of {func_name}({val}): {res}" except TypeError: # شاید چند آرگومان دارد یا نوع متفاوت try: res = fn(arg_str) return f"✅ Result of {func_name}('{arg_str}'): {res}" except Exception as e2: return f"⚠️ Type Mismatch: {e2}" else: return f"❌ Exec Failed: {result_msg}" except Exception as e: return f"❌ Parse/Test Error: {str(e)}" convert_btn.click(handle_conversion, inputs=[code_input], outputs=[status_ws, generated_app_preview, download_btn]) run_test_btn.click(handle_live_test, inputs=[code_input, test_arg_1], outputs=test_output) # --- Bindings for Quran Tab --- def run_quran_analysis(user_input): yield "Processing...", None, None, None, "" verses = parser(user_input) if not verses: yield "❌ Invalid Input.", None, None, None, "" return yield f"Parsing {len(verses)} verses...", None, None, None, "" results = orchestrator.run_full_spectrum_analysis(verses) yield "Generating Vis...", None, None, None, "" vis_plots = create_visualizations(results) report_md = NarrativeGenerator.generate_philosophical_report(results) yield "✅ COMPLETE!", vis_plots.get('cosmic'), vis_plots.get('theology'), vis_plots.get('rhetoric'), report_md btn_quran.click(fn=run_quran_analysis, inputs=[inp_quran], outputs=[stat_quran, plot_cosmic, plot_theology, plot_rhetoric, narrative_quran]) if __name__ == "__main__": demo.launch(share=True) else: print("Please run the core_engine cell first.")