import gradio as gr import os import json import time import uuid from datetime import datetime from groq import Groq import pandas as pd from typing import Dict, List, Tuple, Optional import re import hashlib import sqlite3 # Initialize components def get_groq_client(): api_key = os.getenv("GROQ_API_KEY") if not api_key: raise ValueError("GROQ_API_KEY environment variable not set") return Groq(api_key=api_key) class UserManager: def __init__(self): self.db_path = 'users.db' self.init_database() def init_database(self): """Initialize SQLite database for users""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, email TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, full_name TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP ) ''') cursor.execute(''' CREATE TABLE IF NOT EXISTS chat_sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, session_id TEXT UNIQUE, title TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users (id) ) ''') cursor.execute(''' CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT, role TEXT, content TEXT, timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (session_id) REFERENCES chat_sessions (session_id) ) ''') conn.commit() conn.close() def hash_password(self, password: str) -> str: """Hash password using SHA-256""" return hashlib.sha256(password.encode()).hexdigest() def create_user(self, username: str, email: str, password: str, full_name: str = "") -> Tuple[bool, str]: """Create new user account""" try: conn = sqlite3.connect(self.db_path) cursor = conn.cursor() password_hash = self.hash_password(password) cursor.execute( "INSERT INTO users (username, email, password_hash, full_name) VALUES (?, ?, ?, ?)", (username, email, password_hash, full_name) ) conn.commit() conn.close() return True, "Account created successfully!" except sqlite3.IntegrityError as e: if "username" in str(e): return False, "Username already exists" elif "email" in str(e): return False, "Email already registered" else: return False, "Registration failed" except Exception as e: return False, f"Error: {str(e)}" def authenticate_user(self, username: str, password: str) -> Tuple[bool, Optional[Dict]]: """Authenticate user login""" try: conn = sqlite3.connect(self.db_path) cursor = conn.cursor() password_hash = self.hash_password(password) cursor.execute( "SELECT id, username, email, full_name FROM users WHERE username = ? AND password_hash = ?", (username, password_hash) ) user = cursor.fetchone() if user: cursor.execute( "UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?", (user[0],) ) conn.commit() user_data = { 'id': user[0], 'username': user[1], 'email': user[2], 'full_name': user[3] or user[1] } conn.close() return True, user_data conn.close() return False, None except Exception as e: return False, None class DiagramGenerator: def generate_single_line_diagram(self, config: Dict) -> str: """Generate single line diagram SVG""" return f""" Single Line Diagram G T1 L1 Load """ class PowerSystemsConsultant: def __init__(self): self.groq_client = get_groq_client() self.diagram_generator = DiagramGenerator() self.user_manager = UserManager() self.current_user = None self.current_session = None def generate_response(self, user_query: str, chat_history: List[Tuple[str, str]], session_id: str = None) -> Tuple[str, str]: """Generate response using Groq LLM""" try: # Check if query is asking for a diagram diagram_svg = None if any(keyword in user_query.lower() for keyword in ['diagram', 'single line', 'drawing', 'circuit']): diagram_svg = self.diagram_generator.generate_single_line_diagram({}) # Prepare system prompt system_prompt = """You are a Power Systems Expert AI assistant specializing in electrical power systems. You help with fault analysis, protection systems, standards interpretation, and engineering calculations. Provide clear, technical explanations with practical examples and safety considerations.""" # Prepare conversation context messages = [{"role": "system", "content": system_prompt}] # Add chat history (last 5 exchanges) for human_msg, ai_msg in chat_history[-5:]: messages.append({"role": "user", "content": human_msg}) messages.append({"role": "assistant", "content": ai_msg}) # Add current query messages.append({"role": "user", "content": user_query}) # Generate response using Groq response = self.groq_client.chat.completions.create( model="llama3-70b-8192", messages=messages, max_tokens=2000, temperature=0.8 ) text_response = response.choices[0].message.content return text_response, diagram_svg except Exception as e: error_msg = f"Error generating response: {str(e)}. Please check your GROQ_API_KEY and try again." return error_msg, None def generate_practice_pack(self, topic: str, difficulty: str, num_questions: int) -> str: """Generate practice questions pack""" try: practice_prompt = f"""Generate {num_questions} power systems practice questions about {topic} at {difficulty} level. Format with numbered questions, multiple choice options, and detailed solutions.""" messages = [ {"role": "system", "content": "You are an expert power systems engineer creating practice questions."}, {"role": "user", "content": practice_prompt} ] response = self.groq_client.chat.completions.create( model="llama3-70b-8192", messages=messages, max_tokens=3000, temperature=0.7 ) return response.choices[0].message.content except Exception as e: return f"Error generating practice pack: {str(e)}" def explain_standard(self, standard: str) -> str: """Explain power systems standard""" try: standard_prompt = f"""Provide a comprehensive explanation of the {standard} standard including purpose, key requirements, practical applications, and implementation considerations.""" messages = [ {"role": "system", "content": "You are an expert in power systems standards."}, {"role": "user", "content": standard_prompt} ] response = self.groq_client.chat.completions.create( model="llama3-70b-8192", messages=messages, max_tokens=2500, temperature=0.6 ) return response.choices[0].message.content except Exception as e: return f"Error explaining standard: {str(e)}" def create_chat_session(self, user_id: int, title: str = None) -> str: """Create new chat session""" session_id = str(uuid.uuid4()) try: conn = sqlite3.connect(self.user_manager.db_path) cursor = conn.cursor() cursor.execute( "INSERT INTO chat_sessions (user_id, session_id, title) VALUES (?, ?, ?)", (user_id, session_id, title or f"Chat {datetime.now().strftime('%m/%d %H:%M')}") ) conn.commit() conn.close() return session_id except Exception as e: return str(uuid.uuid4()) # Initialize the consultant try: consultant = PowerSystemsConsultant() initialization_status = "✅ Power Systems Consultant initialized successfully!" except Exception as e: consultant = None initialization_status = f"❌ Initialization failed: {str(e)}" # Updated CSS with lighter background and fixed animations ENHANCED_CSS = """ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); * { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; box-sizing: border-box; } :root { --primary: #3b82f6; --primary-light: #60a5fa; --primary-dark: #2563eb; --secondary: #10b981; --secondary-light: #34d399; --accent: #8b5cf6; --warning: #f59e0b; --danger: #ef4444; --success: #10b981; --bg-primary: #f8fafc; --bg-secondary: #f1f5f9; --bg-tertiary: #e2e8f0; --bg-card: rgba(255, 255, 255, 0.95); --bg-glass: rgba(255, 255, 255, 0.8); --text-primary: #0f172a; --text-secondary: #475569; --text-muted: #64748b; --border: rgba(148, 163, 184, 0.3); --border-light: rgba(148, 163, 184, 0.2); --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1); --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1); --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25); } /* Dark mode for specific elements only */ .dark-section { --bg-primary: #0f172a; --bg-secondary: #1e293b; --bg-tertiary: #334155; --bg-card: rgba(30, 41, 59, 0.9); --text-primary: #f8fafc; --text-secondary: #cbd5e1; --text-muted: #94a3b8; --border: rgba(255, 255, 255, 0.1); } .gradio-container { background: linear-gradient(135deg, var(--bg-primary) 0%, var(--bg-secondary) 50%, var(--bg-tertiary) 100%); color: var(--text-primary); min-height: 100vh; padding: 0; } /* Fixed cover page styling */ .cover-page { min-height: 100vh; background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 30%, #cbd5e1 60%, #94a3b8 100%); display: flex !important; flex-direction: column !important; align-items: center !important; justify-content: center !important; text-align: center; padding: 2rem; position: relative; overflow: hidden; } .cover-page::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(circle at 20% 80%, rgba(59, 130, 246, 0.1) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(139, 92, 246, 0.1) 0%, transparent 50%), radial-gradient(circle at 40% 40%, rgba(16, 185, 129, 0.05) 0%, transparent 50%); pointer-events: none; } .cover-hero { z-index: 10; max-width: 800px; margin-bottom: 4rem; position: relative; } .cover-icon { font-size: 6rem; background: linear-gradient(135deg, var(--primary), var(--accent)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 2rem; display: block; line-height: 1; } .cover-title { font-size: clamp(2.5rem, 6vw, 4.5rem); font-weight: 800; background: linear-gradient(135deg, var(--text-primary), var(--text-secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 1.5rem; line-height: 1.1; position: relative; } .cover-subtitle { font-size: clamp(1rem, 2.5vw, 1.25rem); color: var(--text-secondary); margin-bottom: 3rem; line-height: 1.6; max-width: 600px; margin-left: auto; margin-right: auto; } .cover-buttons { display: flex; gap: 2rem; flex-wrap: wrap; justify-content: center; z-index: 10; position: relative; } .cover-btn { padding: 1.25rem 3rem !important; font-size: 1.1rem !important; font-weight: 600 !important; border-radius: 50px !important; border: none !important; cursor: pointer !important; transition: all 0.3s ease !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; position: relative !important; overflow: hidden !important; min-width: 200px !important; text-decoration: none !important; display: inline-flex !important; align-items: center !important; justify-content: center !important; gap: 0.5rem !important; } .cover-btn-primary { background: linear-gradient(135deg, var(--primary), var(--primary-light)) !important; color: white !important; box-shadow: var(--shadow-lg) !important; } .cover-btn-secondary { background: linear-gradient(135deg, var(--secondary), var(--secondary-light)) !important; color: white !important; box-shadow: var(--shadow-lg) !important; } .cover-btn:hover { transform: translateY(-3px) scale(1.05) !important; box-shadow: var(--shadow-xl) !important; } /* Authentication Pages */ .auth-page { min-height: 100vh; background: linear-gradient(135deg, #f8fafc, #e2e8f0); display: flex; align-items: center; justify-content: center; padding: 2rem; } .auth-container { background: var(--bg-card); backdrop-filter: blur(20px); border: 1px solid var(--border); border-radius: 24px; padding: 3rem; width: 100%; max-width: 450px; box-shadow: var(--shadow-2xl); } .auth-header { text-align: center; margin-bottom: 2.5rem; } .auth-icon { font-size: 3rem; background: linear-gradient(135deg, var(--primary), var(--accent)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 1rem; } .auth-title { font-size: 2rem; font-weight: 700; color: var(--text-primary); margin-bottom: 0.5rem; } .auth-subtitle { color: var(--text-secondary); font-size: 0.95rem; } /* Services Page */ .services-page { min-height: 100vh; background: linear-gradient(135deg, #f8fafc, #e2e8f0, #cbd5e1); padding: 2rem; } .services-header { text-align: center; margin-bottom: 4rem; max-width: 800px; margin-left: auto; margin-right: auto; } .services-title { font-size: clamp(2.5rem, 6vw, 4rem); font-weight: 800; background: linear-gradient(135deg, var(--text-primary), var(--text-secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 1rem; } .services-subtitle { font-size: 1.2rem; color: var(--text-secondary); margin-bottom: 2rem; } .user-welcome { background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px; padding: 1.5rem; margin-bottom: 2rem; text-align: center; backdrop-filter: blur(20px); } .services-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; max-width: 1200px; margin: 0 auto; } .service-card { background: var(--bg-card); backdrop-filter: blur(20px); border: 1px solid var(--border); border-radius: 20px; padding: 2.5rem; text-align: center; transition: all 0.4s ease; cursor: pointer; position: relative; overflow: hidden; } .service-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(135deg, var(--primary), var(--accent)); transform: scaleX(0); transition: transform 0.3s ease; } .service-card:hover::before { transform: scaleX(1); } .service-card:hover { transform: translateY(-8px); border-color: var(--primary); box-shadow: var(--shadow-2xl); } .service-icon { font-size: 4rem; background: linear-gradient(135deg, var(--primary), var(--accent)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 1.5rem; display: block; } .service-title { font-size: 1.5rem; font-weight: 700; color: var(--text-primary); margin-bottom: 1rem; } .service-description { color: var(--text-secondary); line-height: 1.6; margin-bottom: 2rem; } .service-button { background: linear-gradient(135deg, var(--primary), var(--primary-light)) !important; border: none !important; border-radius: 50px !important; padding: 0.875rem 2rem !important; font-weight: 600 !important; color: white !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; transition: all 0.3s ease !important; cursor: pointer !important; } .service-button:hover { transform: translateY(-2px) !important; box-shadow: var(--shadow-lg) !important; } /* Chat Interface */ .dark-section .chatbot-page { background: linear-gradient(135deg, var(--bg-primary), var(--bg-secondary)); min-height: 100vh; display: flex; flex-direction: column; } .dark-section .chatbot-header { background: var(--bg-card); backdrop-filter: blur(20px); border-bottom: 1px solid var(--border); padding: 1.5rem 2rem; color: var(--text-primary); } /* Enhanced Form Inputs */ .gradio-textbox input, .gradio-textbox textarea { background: rgba(255, 255, 255, 0.95) !important; border: 2px solid var(--border) !important; border-radius: 12px !important; padding: 1rem !important; color: var(--text-primary) !important; font-size: 1rem !important; transition: all 0.3s ease !important; } .gradio-textbox input:focus, .gradio-textbox textarea:focus { border-color: var(--primary) !important; box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1) !important; background: white !important; } .gradio-button { background: linear-gradient(135deg, var(--primary), var(--primary-light)) !important; border: none !important; border-radius: 12px !important; padding: 1rem 2rem !important; font-weight: 600 !important; font-size: 1rem !important; color: white !important; cursor: pointer !important; transition: all 0.3s ease !important; text-transform: uppercase !important; letter-spacing: 0.5px !important; } .gradio-button:hover { transform: translateY(-2px) !important; box-shadow: var(--shadow-xl) !important; background: linear-gradient(135deg, var(--primary-light), var(--primary)) !important; } /* Page visibility fixes */ .gradio-column { display: flex !important; flex-direction: column !important; } .gradio-row { display: flex !important; } /* Responsive Design */ @media (max-width: 768px) { .cover-buttons { flex-direction: column; align-items: center; } .cover-btn { width: 100% !important; max-width: 300px !important; } .services-grid { grid-template-columns: 1fr; gap: 1.5rem; } } /* Loading states */ .loading { opacity: 0.7; pointer-events: none; } .loading::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 20px; height: 20px; border: 2px solid var(--primary); border-top: 2px solid transparent; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: translate(-50%, -50%) rotate(0deg); } 100% { transform: translate(-50%, -50%) rotate(360deg); } } /* Prevent unwanted animations */ .cover-page .cover-hero { position: relative !important; transform: none !important; animation: none !important; } .cover-page .cover-title { position: relative !important; transform: none !important; animation: none !important; } """ # Create the multi-page application def create_multipage_app(): with gr.Blocks( theme=gr.themes.Soft( primary_hue=gr.themes.colors.blue, secondary_hue=gr.themes.colors.green, neutral_hue=gr.themes.colors.slate, ), title="⚡ Power Systems Consultant", css=ENHANCED_CSS ) as app: # Global state management current_page = gr.State("cover") user_state = gr.State(None) session_state = gr.State(None) # Page visibility management page_visibility = gr.State({ "cover": True, "signin": False, "signup": False, "services": False, "chatbot": False, "practice": False, "standards": False, "study": False }) # Page 1: Cover Page (Always visible initially) with gr.Column(visible=True, elem_classes=["cover-page"]) as cover_page: with gr.HTML() as cover_content: gr.HTML("""

Power Systems Consultant

Advanced AI-powered platform for electrical power systems analysis, fault calculations, protection design, and engineering excellence. Experience the future of power systems consulting.

""") with gr.Row(): signin_nav_btn = gr.Button("🔐 Sign In", elem_classes=["cover-btn", "cover-btn-primary"]) signup_nav_btn = gr.Button("🚀 Create Account", elem_classes=["cover-btn", "cover-btn-secondary"]) # Page 2: Sign In Page with gr.Column(visible=False, elem_classes=["auth-page"]) as signin_page: with gr.Column(elem_classes=["auth-container"]): gr.HTML("""
🔐

Welcome Back

Sign in to your Power Systems workspace

""") login_username = gr.Textbox( label="Username", placeholder="Enter your username" ) login_password = gr.Textbox( label="Password", type="password", placeholder="Enter your password" ) with gr.Row(): signin_btn = gr.Button("Sign In", variant="primary") back_cover_signin = gr.Button("← Back", variant="secondary") signin_status = gr.Textbox(label="Status", interactive=False, visible=False) # Page 3: Sign Up Page with gr.Column(visible=False, elem_classes=["auth-page"]) as signup_page: with gr.Column(elem_classes=["auth-container"]): gr.HTML("""
🚀

Join Our Community

Create your Power Systems workspace

""") reg_username = gr.Textbox( label="Username", placeholder="Choose a unique username" ) reg_email = gr.Textbox( label="Email", placeholder="your.email@domain.com" ) reg_full_name = gr.Textbox( label="Full Name", placeholder="Your full name" ) reg_password = gr.Textbox( label="Password", type="password", placeholder="Create a strong password (min 6 chars)" ) reg_confirm_password = gr.Textbox( label="Confirm Password", type="password", placeholder="Confirm your password" ) with gr.Row(): signup_btn = gr.Button("Create Account", variant="primary") back_cover_signup = gr.Button("← Back", variant="secondary") signup_status = gr.Textbox(label="Status", interactive=False, visible=False) # Page 4: Services Selection Page with gr.Column(visible=False, elem_classes=["services-page"]) as services_page: gr.HTML("""

Power Systems Workspace

Choose your engineering tool and start analyzing power systems

👤

Welcome to Power Systems!

Ready to tackle power systems challenges?

""") with gr.Row(): with gr.Column(elem_classes=["service-card"]): gr.HTML("""
🤖

AI Consultant

Interactive chat with AI expert for fault analysis, protection systems, calculations, and engineering guidance with diagram generation.

""") chatbot_service_btn = gr.Button("Launch Consultant", elem_classes=["service-button"]) with gr.Column(elem_classes=["service-card"]): gr.HTML("""
📚

Practice Generator

Generate customized practice questions with detailed solutions, step-by-step calculations, and standards references for exam prep.

""") practice_service_btn = gr.Button("Generate Practice", elem_classes=["service-button"]) with gr.Row(): with gr.Column(elem_classes=["service-card"]): gr.HTML("""
📋

Standards Explorer

Comprehensive explanations of IEEE, IEC, and international standards with practical applications and implementation guidelines.

""") standards_service_btn = gr.Button("Explore Standards", elem_classes=["service-button"]) with gr.Column(elem_classes=["service-card"]): gr.HTML("""
🎓

Study Resources

Essential formulas, concepts, calculations, and comprehensive exam preparation materials for power systems engineering.

""") study_service_btn = gr.Button("Access Resources", elem_classes=["service-button"]) with gr.Row(): logout_btn = gr.Button("🚪 Sign Out", variant="secondary") # Page 5: Chatbot Interface with gr.Column(visible=False, elem_classes=["dark-section"]) as chatbot_page: with gr.Column(elem_classes=["chatbot-page"]): gr.HTML("""

🤖 AI Power Systems Consultant

""") with gr.Row(): back_services_chat = gr.Button("← Back to Services", variant="secondary") new_chat_btn = gr.Button("➕ New Chat", variant="primary") # Chat interface chatbot = gr.Chatbot( height=400, show_label=False, avatar_images=("👤", "🤖") ) # Diagram display diagram_display = gr.HTML("""
📐

Professional engineering diagrams will appear here

""") # Input area with gr.Row(): msg = gr.Textbox( placeholder="Ask about faults, protection, calculations, or request diagrams...", show_label=False, lines=3, scale=4 ) with gr.Column(scale=1): submit_btn = gr.Button("🚀 Send", variant="primary") clear_btn = gr.Button("🗑️ Clear", variant="secondary") # Page 6: Practice Generator with gr.Column(visible=False, elem_classes=["services-page"]) as practice_page: gr.HTML("""

📚 Practice Generator

AI-generated practice questions with detailed solutions

""") back_services_practice = gr.Button("← Back to Services", variant="secondary") with gr.Row(): with gr.Column(scale=1): gr.HTML('

⚙️ Customize Practice Pack

') topic_input = gr.Dropdown( choices=[ "Fault Analysis", "Protection Systems", "Power Flow", "Stability Studies", "Relay Coordination", "Transformers", "Transmission Lines", "Load Flow", "Short Circuit Analysis", "Harmonics", "Power Quality", "SCADA Systems" ], label="Select Topic", value="Fault Analysis" ) difficulty_input = gr.Radio( choices=["Beginner", "Intermediate", "Advanced"], label="Difficulty Level", value="Intermediate" ) num_questions_input = gr.Slider( minimum=5, maximum=20, step=1, value=10, label="Number of Questions" ) generate_btn = gr.Button("Generate Practice Pack", variant="primary") with gr.Column(scale=2): practice_output = gr.Textbox( label="Generated Practice Pack", lines=25, placeholder="Your customized practice questions will appear here...", show_label=False ) # Page 7: Standards Explorer with gr.Column(visible=False, elem_classes=["services-page"]) as standards_page: gr.HTML("""

📋 Standards Explorer

Comprehensive power systems standards library

""") back_services_standards = gr.Button("← Back to Services", variant="secondary") with gr.Row(): with gr.Column(scale=1): gr.HTML('

📖 Explore Standards

') standard_input = gr.Dropdown( choices=[ "IEEE C37.2 - Device Function Numbers", "IEEE 1547 - Distributed Generation", "IEEE 519 - Harmonic Control", "IEEE C57.12.00 - Transformers", "IEC 61850 - Substation Automation", "IEC 60909 - Short-Circuit Calculations", "IEC 61131 - PLC Programming", "IEC 60255 - Electrical Relays", "ANSI C84.1 - Voltage Ratings", "IEEE 242 - Protection & Coordination", "IEEE 399 - Industrial Power Systems", "IEEE C37.010 - Application Guide" ], label="Select Standard", value="IEEE C37.2 - Device Function Numbers" ) explain_btn = gr.Button("Explain Standard", variant="primary") with gr.Column(scale=2): standard_output = gr.Textbox( label="Standard Explanation", lines=25, placeholder="Detailed standard explanation will appear here...", show_label=False ) # Page 8: Study Resources with gr.Column(visible=False, elem_classes=["services-page"]) as study_page: gr.HTML("""

🎓 Study Resources

Essential formulas and exam preparation materials

""") back_services_study = gr.Button("← Back to Services", variant="secondary") with gr.Accordion("⚡ Fault Analysis Formulas", open=True): gr.HTML("""

⚡ Three-Phase Fault Current

I_fault = V_nominal / Z_total

⚠️ Line-to-Ground Fault

I_fault = 3 × V_nominal / (Z1 + Z2 + Z0)

↔️ Line-to-Line Fault

I_fault = √3 × V_nominal / (Z1 + Z2)
""") with gr.Accordion("🛡️ Protection System Principles", open=False): gr.HTML("""

🛡️ Overcurrent Protection

Time Characteristics
  • Inverse Time Curves
  • Coordination Intervals (0.2-0.5s)
  • Pickup Settings (1.25-1.5 × FLA)
  • Time Dial Adjustments
Curve Types
  • Standard Inverse (SI)
  • Very Inverse (VI)
  • Extremely Inverse (EI)
  • Definite Time
""") with gr.Accordion("📐 Power System Calculations", open=False): gr.HTML("""

🧮 Three-Phase Power Formulas

Real Power
P = √3 × V × I × cos(φ)
Reactive Power
Q = √3 × V × I × sin(φ)
""") # Interactive Calculator gr.HTML("""

🧮 Power Systems Calculator

""") with gr.Row(): with gr.Column(): calc_voltage = gr.Number(label="Voltage (V)", value=480) calc_current = gr.Number(label="Current (A)", value=100) calc_pf = gr.Slider(0.1, 1.0, 0.85, label="Power Factor", step=0.01) calc_btn = gr.Button("Calculate Power", variant="primary") with gr.Column(): calc_results = gr.HTML("""
🧮

Enter values and click Calculate

""") # Event handler functions def show_page(target_page, current_visibility): """Update page visibility""" new_visibility = {key: False for key in current_visibility.keys()} new_visibility[target_page] = True return new_visibility def handle_signin(username, password): if not consultant: return gr.update(), gr.update(), gr.update(), gr.update(), None, "System not initialized" if not username or not password: return gr.update(), gr.update(), gr.update(), gr.update(), None, "Please enter both username and password" success, user_data = consultant.user_manager.authenticate_user(username, password) if success: return ( gr.update(visible=False), # Hide signin page gr.update(visible=False), # Hide signup page gr.update(visible=False), # Hide cover page gr.update(visible=True), # Show services page user_data, # Store user data f"Welcome back, {user_data['full_name']}!" ) else: return gr.update(), gr.update(), gr.update(), gr.update(), None, "Invalid credentials" def handle_signup(username, email, password, confirm_password, full_name): if not consultant: return gr.update(), gr.update(), gr.update(), gr.update(), None, "System not initialized" if not all([username, email, password, confirm_password]): return gr.update(), gr.update(), gr.update(), gr.update(), None, "Please fill all fields" if password != confirm_password: return gr.update(), gr.update(), gr.update(), gr.update(), None, "Passwords do not match" if len(password) < 6: return gr.update(), gr.update(), gr.update(), gr.update(), None, "Password must be at least 6 characters" success, message = consultant.user_manager.create_user(username, email, password, full_name) if success: # Auto-login after successful registration success, user_data = consultant.user_manager.authenticate_user(username, password) if success: return ( gr.update(visible=False), # Hide signin page gr.update(visible=False), # Hide signup page gr.update(visible=False), # Hide cover page gr.update(visible=True), # Show services page user_data, # Store user data "Account created and logged in successfully!" ) return gr.update(), gr.update(), gr.update(), gr.update(), None, message def handle_new_chat(user_data): if not consultant or not user_data: return None, [] session_id = consultant.create_chat_session(user_data['id']) return session_id, [] def handle_chat_message(message, history, user_data, session_id): if not consultant or not user_data: return history, "", None if not message.strip(): return history, message, None try: response, diagram_svg = consultant.generate_response(message, history, session_id) new_history = history + [[message, response]] # Update diagram display if available if diagram_svg: diagram_html = f'
{diagram_svg}
' else: diagram_html = """
📐

Professional engineering diagrams will appear here

""" return new_history, "", diagram_html except Exception as e: return history + [[message, f"Error: {str(e)}"]], "", None def clear_chat(): return [], "", """
📐

Professional engineering diagrams will appear here

""" def handle_practice_generation(topic, difficulty, num_questions, user_data): if not consultant or not user_data: return "Please log in to access this feature." try: return consultant.generate_practice_pack(topic, difficulty, int(num_questions)) except Exception as e: return f"Error generating practice pack: {str(e)}" def handle_standard_explanation(standard, user_data): if not consultant or not user_data: return "Please log in to access this feature." try: return consultant.explain_standard(standard) except Exception as e: return f"Error explaining standard: {str(e)}" def calculate_power(voltage, current, pf): if voltage and current and pf: p = (3**0.5) * voltage * current * pf / 1000 # kW q = (3**0.5) * voltage * current * ((1-pf**2)**0.5) / 1000 # kVAR s = (3**0.5) * voltage * current / 1000 # kVA return f"""

📊 Calculation Results

Real Power

{p:.2f} kW

Reactive Power

{q:.2f} kVAR

Apparent Power

{s:.2f} kVA

""" else: return """
⚠️

Please enter valid values for all fields

""" # Navigation event handlers signin_nav_btn.click( fn=lambda: (gr.update(visible=False), gr.update(visible=True), gr.update(visible=False)), outputs=[cover_page, signin_page, signup_page] ) signup_nav_btn.click( fn=lambda: (gr.update(visible=False), gr.update(visible=False), gr.update(visible=True)), outputs=[cover_page, signin_page, signup_page] ) back_cover_signin.click( fn=lambda: (gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), outputs=[cover_page, signin_page, signup_page] ) back_cover_signup.click( fn=lambda: (gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), outputs=[cover_page, signin_page, signup_page] ) # Authentication event handlers signin_btn.click( fn=handle_signin, inputs=[login_username, login_password], outputs=[signin_page, signup_page, cover_page, services_page, user_state, signin_status] ) signup_btn.click( fn=handle_signup, inputs=[reg_username, reg_email, reg_password, reg_confirm_password, reg_full_name], outputs=[signin_page, signup_page, cover_page, services_page, user_state, signup_status] ) # Service navigation chatbot_service_btn.click( fn=lambda: (gr.update(visible=False), gr.update(visible=True)), outputs=[services_page, chatbot_page] ) practice_service_btn.click( fn=lambda: (gr.update(visible=False), gr.update(visible=True)), outputs=[services_page, practice_page] ) standards_service_btn.click( fn=lambda: (gr.update(visible=False), gr.update(visible=True)), outputs=[services_page, standards_page] ) study_service_btn.click( fn=lambda: (gr.update(visible=False), gr.update(visible=True)), outputs=[services_page, study_page] ) # Back to services navigation back_services_chat.click( fn=lambda: (gr.update(visible=True), gr.update(visible=False)), outputs=[services_page, chatbot_page] ) back_services_practice.click( fn=lambda: (gr.update(visible=True), gr.update(visible=False)), outputs=[services_page, practice_page] ) back_services_standards.click( fn=lambda: (gr.update(visible=True), gr.update(visible=False)), outputs=[services_page, standards_page] ) back_services_study.click( fn=lambda: (gr.update(visible=True), gr.update(visible=False)), outputs=[services_page, study_page] ) # Logout handler logout_btn.click( fn=lambda: (gr.update(visible=True), gr.update(visible=False), None, None), outputs=[cover_page, services_page, user_state, session_state] ) # Chat functionality new_chat_btn.click( fn=handle_new_chat, inputs=[user_state], outputs=[session_state, chatbot] ) submit_btn.click( fn=handle_chat_message, inputs=[msg, chatbot, user_state, session_state], outputs=[chatbot, msg, diagram_display] ) msg.submit( fn=handle_chat_message, inputs=[msg, chatbot, user_state, session_state], outputs=[chatbot, msg, diagram_display] ) clear_btn.click( fn=clear_chat, outputs=[chatbot, msg, diagram_display] ) # Practice generator functionality generate_btn.click( fn=handle_practice_generation, inputs=[topic_input, difficulty_input, num_questions_input, user_state], outputs=[practice_output] ) # Standards explorer functionality explain_btn.click( fn=handle_standard_explanation, inputs=[standard_input, user_state], outputs=[standard_output] ) # Calculator functionality calc_btn.click( fn=calculate_power, inputs=[calc_voltage, calc_current, calc_pf], outputs=[calc_results] ) return app # Launch the application if __name__ == "__main__": app = create_multipage_app() # Enhanced startup information print("⚡" * 60) print("🚀 POWER SYSTEMS MULTI-PAGE CONSULTANT v4.0 - FIXED") print("⚡" * 60) print() print("🔧 FIXES IMPLEMENTED:") print(" ✅ Fixed disappearing title issue on cover page") print(" ✅ Lightened background - no more dark theme") print(" ✅ Fixed page movement and scroll issues") print(" ✅ Improved page visibility management") print(" ✅ Enhanced navigation between pages") print(" ✅ Fixed CSS animations and transitions") print(" ✅ Better responsive design") print(" ✅ Cleaner authentication flow") print() print("🎨 MODERN MULTI-PAGE INTERFACE:") print(" ✨ Stable cover page with proper title display") print(" 🔐 Separate authentication pages (Sign In/Sign Up)") print(" 🎯 Interactive service selection dashboard") print(" 💬 Dedicated chatbot interface with diagrams") print(" 📚 Full-featured practice generator") print(" 📋 Comprehensive standards explorer") print(" 🎓 Interactive study resources with calculator") print(" 🌊 Smooth and stable page transitions") print() print("🔧 CORE FEATURES:") print(" 🤖 AI-powered chat consultant with diagram generation") print(" 📊 Professional engineering diagrams (SVG)") print(" 🎯 Customizable practice question generator") print(" 📋 Standards library with detailed explanations") print(" 🧮 Built-in power systems calculator") print(" 💾 User authentication & persistent sessions") print(" 📜 Chat history management") print(" ⌨️ Enhanced keyboard shortcuts") print() print("🎨 DESIGN HIGHLIGHTS:") print(" 🌈 Light, modern color palette (blue/green/purple accents)") print(" ✨ Glass-morphism effects and clean borders") print(" 📱 Fully responsive design") print(" 🎭 Stable page transitions without content jumping") print(" 💫 Interactive hover effects") print(" 🌊 Professional gradient backgrounds") print() if consultant is None: print("⚠️ WARNING: System not fully initialized") print(" Please ensure GROQ_API_KEY is set in environment") print(" Some features may be limited without API access") else: print("✅ SYSTEM STATUS: All systems operational!") print() print("🌐 ACCESS INFORMATION:") print(" 📍 Local URL: http://localhost:7860") print(" 🔒 Start with cover page → Sign In/Sign Up") print(" 🎯 Choose your service from dashboard") print(" 💬 Experience the enhanced chatbot interface") print() print("🚀 USAGE FLOW:") print(" 1️⃣ Cover Page: Welcome screen with navigation") print(" 2️⃣ Authentication: Sign in or create account") print(" 3️⃣ Services Dashboard: Choose your tool") print(" 4️⃣ Service Pages: Use AI consultant, practice, etc.") print(" 5️⃣ Navigation: Easy back buttons to return") print() print("💡 KEY IMPROVEMENTS:") print(" 🎯 Fixed title disappearing after 2 seconds") print(" 🎯 Stopped page content from moving down") print(" 🎯 Lighter, more professional appearance") print(" 🎯 Better error handling and user feedback") print(" 🎯 Improved responsive design for mobile") print(" 🎯 Cleaner code structure and organization") print() print("💫 Experience the stable, professional power systems platform!") print("⚡" * 60) try: app.launch( server_name="0.0.0.0", server_port=7860, share=False, show_api=False, show_error=True, quiet=False, favicon_path=None, ssl_verify=False ) except Exception as e: print(f"❌ Launch Error: {str(e)}") print("💡 Try running with different port or check firewall settings")