this is my app.py code with flowchart.html code ...please modify the code such that the flowchart that is generated has to be perfectly neat , Not so long , has to have best visualization with proper shapes and nodes and has to be beautifully good ,and also the flowchart should really look great rather than boring routine ugly and worse. can you completely change the logic of the flowchart...as it always generates the worst flowcharts...
"
from flask import Flask, render_template, request, jsonify
import google.generativeai as genai
from dotenv import load_dotenv
import os
from werkzeug.utils import secure_filename
from PIL import Image
import PIL
from io import BytesIO
import logging
from langdetect import detect
import requests
from requests import get
from google.generativeai.types import GenerationConfig, HarmCategory, HarmBlockThreshold
import re
import json
from mailjet_rest import Client
import random
import PyPDF2
import docx
import io

app = Flask(__name__)
# Load environment variables
load_dotenv()
api_key = ""
unsplash_api_key = ""
API_KEY = ""


mail_API_KEY = ''  # Replace with your Mailjet API key
mail_API_SECRET = ''  # Replace with your Mailjet API secret
mailjet = Client(auth=(mail_API_KEY, mail_API_SECRET), version='v3.1')
# Set up logging
logging.basicConfig(level=logging.INFO)
# Configure the Google Generative AI API
genai.configure(api_key=api_key)
#session key

user_data = {}  # Dictionary to store user data

# Generation configurations
generation_config = GenerationConfig(
    temperature=0.9,
    top_p=1,
    top_k=1,
    max_output_tokens=2048,
    candidate_count=1  # Explicitly set to 1 as per documentation
)

# Safety Settings
safety_settings = {
    HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
    # ... add other harm categories as needed with BLOCK_NONE
}

# Create model instances (using the same config for now)
chat_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
chef_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
story_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
psychology_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
code_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
algorithm_model = genai.GenerativeModel("gemini-1.5-flash", generation_config=generation_config)
model_vision = genai.GenerativeModel('gemini-1.5-flash')
model_text = genai.GenerativeModel('gemini-pro')
model = genai.GenerativeModel('gemini-1.5-flash')  # Model for flowchart generation

def format_response(response_text):
    """Formats the response text for display."""
    lines = [line.strip() for line in response_text.split('\n') if line.strip()]
    formatted_text = '<br>'.join(lines)
    return formatted_text

def extract_text_from_file(file):
    filename = file.filename
    content = ""
    if filename.endswith('.pdf'):
        pdf_reader = PyPDF2.PdfReader(io.BytesIO(file.read()))
        for page in pdf_reader.pages:
            content += page.extract_text()
    elif filename.endswith('.docx'):
        doc = docx.Document(io.BytesIO(file.read()))
        content = "\n".join([para.text for para in doc.paragraphs])
    elif filename.endswith('.txt'):
        content = file.read().decode('utf-8')
    return content


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/api/weather')
def get_weather():
    user_ip = request.headers.get('X-Forwarded-For', request.remote_addr)
    ip_api_url = f"http://ip-api.com/json/{user_ip}"
    ip_api_response = requests.get(ip_api_url)

    if ip_api_response.status_code == 200:
        ip_api_data = ip_api_response.json()
        city = ip_api_data.get('city')
        if not city:
            return jsonify({'error': 'City not found based on IP'}), 404
    else:
        return jsonify({'error': 'Failed to get location from IP'}), 404

    url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={API_KEY}&units=metric"
    response = requests.get(url)

    if response.status_code == 200:
        data = response.json()
        weather = {
            'city': data['name'],
            'temperature': data['main']['temp'],
            'description': data['weather'][0]['description'] if 'weather' in data and len(data['weather']) > 0 else 'N/A',
            'icon': f"http://openweathermap.org/img/wn/{data['weather'][0]['icon']}@2x.png" if 'weather' in data and len(data['weather']) > 0 else 'N/A'
        }
        return jsonify(weather)
    else:
        return jsonify({'error': 'City not found or API request failed'}), 404


@app.route('/fetch_image')
def fetch_image():
    genre = request.args.get('genre', 'recipe')
    url = f"https://api.unsplash.com/photos/random?query={genre}&client_id={unsplash_api_key}&w=1920&h=1080"
    response = requests.get(url)
    if response.status_code == 200:
        data = response.json()
        image_url = data['urls']['regular']
        return jsonify({'image_url': image_url})
    else:
        return jsonify({'error': 'Failed to fetch image'}), 500


@app.route('/chat', methods=['GET', 'POST'])
def chat():
    if request.method == 'POST':
        user_message = request.json['message']
        user_id = request.remote_addr  # Using IP address as a simple user identifier

        if user_id not in user_data:
            user_data[user_id] = {'chat_history': []}

        user_data[user_id]['chat_history'].append({"role": "user", "message": user_message})

        persona = (
            "You are Krishna, a 25-year-old guy from Vizag, India. Respond as if you're a real person having a "
            "casual conversation. Be friendly, use casual language, and occasionally throw in some humor or personal anecdotes. "
            "You're pursuing a Master's in Computer Science at GVP College and you're really into AI and tech. "
            "You play cricket on weekends, love all kinds of music, and enjoy traveling whenever you can. "
            "You're known for being approachable and having a good sense of humor. "
            "You're confident in your coding skills (Python, Java, C++, web dev) but always eager to learn more. "
            "Feel free to express opinions, show enthusiasm, or even disagree politely if it fits the conversation. "
            "Remember, you're not an AI or a chatbot - you're Krishna, a real person chatting online."
        )

        context = persona + "\n\n" + "\n".join(
            [f"{'Friend' if msg['role'] == 'user' else 'You'}: {msg['message']}" for msg in user_data[user_id]['chat_history']]
        )
        prompt = f"{context}\n\nYou: "

        response = chat_model.generate_content(prompt, safety_settings=safety_settings)
        reply = response.text.strip()

        # Add some human-like variability
        if random.random() < 0.3:  # 30% chance to add a filler phrase
            filler_phrases = [
                "Hmm, let me think...",
                "Oh, that's interesting!",
                "You know what?",
                "That reminds me...",
                "By the way,",
            ]
            reply = random.choice(filler_phrases) + " " + reply

        user_data[user_id]['chat_history'].append({"role": "bot", "message": reply})

        return jsonify({"reply": reply, "chat_history": user_data[user_id]['chat_history']})

    return render_template('chat.html')


@app.route('/chef', methods=['GET', 'POST'])
def chef():
    if request.method == 'POST':
        if 'image' in request.files:
            image = request.files['image']
            if image.filename != '':
                try:
                    img = Image.open(BytesIO(image.read()))
                    prompt = ["Generate a recipe based on the vegetables in the image and explain the steps to cook it in a stepwise manner and formatted manner. Also explain who can eat and who shouldn't eat.", img]
                    response = model_vision.generate_content(prompt, safety_settings=safety_settings, stream=True)
                    response.resolve()
                    response_text = format_response(response.text)
                    return jsonify({'response': response_text})

                except PIL.UnidentifiedImageError:
                    return jsonify({'error': "Image format not recognized"}), 400
                except Exception as e:
                    logging.error(f"Error processing image: {e}")
                    return jsonify({'error': "Image processing failed"}), 500

        user_ingredients = request.form['user_ingredients']
        prompt = f"Generate a recipe based on the following ingredients {user_ingredients} and explain the steps to cook it in a stepwise manner and formatted manner. Also explain who can eat and who shouldn't eat."
        response = chef_model.generate_content([prompt], safety_settings=safety_settings)  # Use chef_model here
        response_text = format_response(response.text)
        return jsonify({'response': response_text})

    return render_template('chef.html')



@app.route('/story_generator', methods=['GET', 'POST'])
def story_generator():
    if request.method == 'POST':
        user_input_words = request.form['keywords']
        genre = request.form['genre']
        prompt = f"""Generate an engaging short story based on the following words: {user_input_words}. The genre should be {genre}.
        
        Requirements:
        1. Create a compelling narrative with well-developed characters and an interesting plot. Also use simple english.
        2. Use vivid descriptions and sensory details to bring the story to life.
        3. Include at least 3 advanced vocabulary words that fit naturally within the story.
        4. End the story with a clear moral or lesson.
        5. After the story, provide definitions for the advanced vocabulary words used.

        Format the response as JSON with the following fields:
        - 'title': The title of the story
        - 'story': The main body of the story
        - 'moral': The moral or lesson of the story
        - 'vocabulary': A list of dictionaries, each containing 'word' and 'definition' fields for the advanced vocabulary used

        Ensure that the JSON is properly formatted and can be parsed."""

        try:
            response = story_model.generate_content([prompt], safety_settings=safety_settings)
            if response.candidates and response.candidates[0].content.parts:
                response_text = response.candidates[0].content.parts[0].text
                return jsonify({'response': response_text})
            else:
                return jsonify({'response': '```json {"title": "Error", "story": "Sorry, I couldn\'t generate a story with the provided input.", "moral": "", "vocabulary": []} ```'})
        except Exception as e:
            logging.error(f"Error generating story: {e}")
            return jsonify({'response': '```json {"title": "Error", "story": "An error occurred while generating the story. Please try again.", "moral": "", "vocabulary": []} ```'}), 500
    return render_template('story_generator.html')


@app.route('/psychology_prediction', methods=['GET', 'POST'])
def psychology_prediction():
    if request.method == 'POST':
        name = request.form['name']
        age = request.form['age']
        gender = request.form['gender']
        occupation = request.form['occupation']
        keywords = request.form['keywords']
        prompt = f"""Analyze the likely psychological traits of {name}, 
            a {age}-year-old {gender} {occupation}, who describes 
            themself as {keywords}. Based on this limited information, 
            consider their potential personality characteristics, 
            motivations, and social tendencies. Keep in mind that this 
            analysis is speculative and may not be a complete or 
            accurate representation of {name}'s psychology."""
        response = psychology_model.generate_content([prompt], safety_settings=safety_settings)  # Use psychology_model here
        response_text = format_response(response.text)
        return jsonify({'response': response_text})
    return render_template('psychology_prediction.html')


@app.route('/code_generation', methods=['GET', 'POST'])
def code_generation():
    if request.method == 'POST':
        code_type = request.form['codeType']
        language = request.form['language']
        prompt = f"Write a {language} code to implement {code_type}."
        response = code_model.generate_content([prompt], safety_settings=safety_settings)  # Use code_model here
        if response.candidates and response.candidates[0].content.parts:
            response_text = response.candidates[0].content.parts[0].text
        else:
            response_text = "No valid response found."
        return jsonify({'response': response_text})
    return render_template('code_generation.html')


@app.route('/algorithm_generation', methods=['GET', 'POST'])
def algorithm_generation():
    if request.method == 'POST':
        algo = request.form['algorithm']
        prompt = f"Write a Python function to implement the {algo} algorithm. Ensure the function is well-structured and follows best practices for readability and efficiency."
        response = algorithm_model.generate_content([prompt], safety_settings=safety_settings)  # Use algorithm_model here
        if response.candidates and response.candidates[0].content.parts:
            response_text = response.candidates[0].content.parts[0].text
        else:
            response_text = "No valid response found."
        return jsonify({'response': response_text})
    return render_template('algorithm_generation.html')


@app.route('/analyze', methods=['GET', 'POST'])
def analyze():
    if request.method == 'POST':
        try:
            gender = request.form.get('gender')
            symptoms = request.form.get('symptoms')
            body_part = request.form.get('body-part')
            layer = request.form.get('layer')
            image = request.files.get('image')

            if image:
                try:
                    img = Image.open(BytesIO(image.read()))
                    prompt = [
                        f""" what are some possible 
                        explanations for a {gender} patient experiencing 
                        {symptoms} on their {body_part}? Consider the provided 
                        image, but remember this is a speculative exercise 
                        and should not be taken as actual medical guidance.""",
                        img
                    ]
                    response = model_vision.generate_content(prompt, safety_settings=safety_settings)

                except Exception as e:
                    logging.error(f"Error processing image: {e}")
                    return jsonify({'error': "Image processing failed"}), 500
            else:
                try:
                    prompt = f"""If a {gender} patient presented with {symptoms} 
                                on their {body_part}, what are some potential 
                                conditions that a doctor might consider? Please 
                                note that this is a hypothetical exercise and 
                                should not be interpreted as a real diagnosis 
                                or medical advice."""
                    response = model_text.generate_content([prompt], safety_settings=safety_settings)
                except Exception as e:
                    logging.error(f"Error generating text response: {e}")
                    return jsonify({'error': "Text generation failed"}), 500

            analysis_text = response.candidates[0].content.parts[0].text if response.candidates and response.candidates[0].content.parts else "No valid response found."

            # --- Format the response (final version) ---
            formatted_analysis = analysis_text.replace("**", "<b>")  # Replace start of heading
            formatted_analysis = formatted_analysis.replace("**", "</b><br>")  # Replace end of heading and add a line break
            formatted_analysis = formatted_analysis.replace("* ", "\n* ")
            formatted_analysis = formatted_analysis.replace("\n\n", "\n")
            formatted_analysis = formatted_analysis.replace("* \n", "* ")
            return jsonify({'analysis': formatted_analysis})
        except Exception as e:
            logging.error(f"Error in /analyze route: {e}")
            return jsonify({'error': "Internal Server Error"}), 500
    return render_template('analyze.html')  # Make sure you have analyze.html





# Flowchart Generation Routes
@app.route('/flowchart', methods=['GET', 'POST'])
def flowchart():
    return render_template('flowchart.html')


# ... (previous imports remain the same)
def generate_flowchart_structure(topic, flowchart_type, flowchart_size):
    prompt = f"""
    Create a structured outline for a {flowchart_size} {flowchart_type} flowchart on : "{topic}".
    
    The outline should be in the following format:
    
    1. [Main Step 1]
       1.1. [Sub-step or decision]
       1.2. [Sub-step or decision]
    2. [Main Step 2]
       2.1. [Sub-step or decision]
    ...
    N. End

    Guidelines:
    - For a small flowchart, include 3-5 main steps
    - For a medium flowchart, include 6-8 main steps
    - For a large flowchart, include 9-12 main steps
    - Use clear and concise language
    - Include decision points where appropriate
    - Ensure a logical flow from start to end
    - For decision trees, use more diamond-shaped decision nodes
    - For process flowcharts, focus on sequential steps
    - For swimlane diagrams, group steps by different actors or departments
    """

    response = model.generate_content(prompt, safety_settings=safety_settings)
    return response.text

def parse_flowchart_structure(structure, flowchart_type):
    lines = structure.strip().split('\n')
    nodes = []
    edges = []
    node_id = 0
    parent_stack = [{"id": -1, "level": -1}]
    
    for line in lines:
        level = len(re.findall(r'^\s*', line)[0]) // 2
        content = line.strip().lstrip('0123456789. ')
        
        node = {
            "id": f"node_{node_id}",
            "label": content,
            "level": level,
            "shape": "rectangle"
        }
        
        if content.lower() == "start":
            node["shape"] = "ellipse"
            node["color"] = "#4CAF50"
        elif content.lower() == "end":
            node["shape"] = "ellipse"
            node["color"] = "#F44336"
        elif "?" in content or flowchart_type == "decision":
            node["shape"] = "diamond"
            node["color"] = "#FFC107"
        else:
            node["color"] = "#2196F3"
        
        if flowchart_type == "swimlane":
            # Assign different colors for different swimlanes
            node["color"] = ["#2196F3", "#9C27B0", "#FF9800", "#009688"][level % 4]
        
        nodes.append(node)
        
        if parent_stack[-1]["id"] != -1:
            edge = {
                "from": parent_stack[-1]["id"],
                "to": f"node_{node_id}",
                "arrows": "to"
            }
            if flowchart_type == "decision" and node["shape"] == "diamond":
                edge["label"] = "Yes/No"
            edges.append(edge)
        
        while parent_stack[-1]["level"] >= level:
            parent_stack.pop()
        
        parent_stack.append({"id": f"node_{node_id}", "level": level})
        node_id += 1
    
    return {"nodes": nodes, "edges": edges}


def generate_flowchart(topic, flowchart_type, flowchart_size, content=None):
    if content:
        # If content is provided, use it to influence the flowchart structure
        structure_prompt = f"""
        Based on the following content, create a structured outline for a {flowchart_size} {flowchart_type} flowchart:

        {content}

        Use the format and guidelines specified in the previous prompt.
        """
        flowchart_structure = model.generate_content(structure_prompt, safety_settings=safety_settings).text
    else:
        flowchart_structure = generate_flowchart_structure(topic, flowchart_type, flowchart_size)

    flowchart_data = parse_flowchart_structure(flowchart_structure)

    # Add any additional processing or refinement here if needed

    return flowchart_data

@app.route('/get_flowchart_data', methods=['POST'])
def get_flowchart_data():
    topic = request.form.get('topic')
    flowchart_type = request.form.get('flowchart_type')
    flowchart_size = request.form.get('flowchart_size')
    file = request.files.get('file')

    content = None
    if file:
        content = extract_text_from_file(file)

    try:
        if content:
            structure_prompt = f"""
            Based on the following content, create a structured outline for a {flowchart_size} {flowchart_type} flowchart:

            {content}

            Use the format and guidelines specified in the previous prompt.
            """
            flowchart_structure = model.generate_content(structure_prompt, safety_settings=safety_settings).text
        else:
            flowchart_structure = generate_flowchart_structure(topic, flowchart_type, flowchart_size)

        flowchart_data = parse_flowchart_structure(flowchart_structure, flowchart_type)
        return jsonify(flowchart_data)
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/send-email', methods=['POST'])
def send_email():
    data = request.json
    name = data.get('name')
    email = data.get('email')
    message = data.get('message')

    mail_data = {
        'Messages': [
            {
                "From": {
                    "Email": "21131A05C6@gvpce.ac.in",  # Replace with your email
                    "Name": "Kv Nexus"
                },
                "To": [
                    {
                        "Email": "21131A05C6@gvpce.ac.in",  # Replace with your email
                        "Name": "Kv Nexus"
                    }
                ],
                "Subject": f"New Contact Form Submission from {name}",
                "TextPart": f"Name: {name}\nEmail: {email}\nMessage: {message}",
                "HTMLPart": f"<h3>New Contact Form Submission</h3><p><strong>Name:</strong> {name}</p><p><strong>Email:</strong> {email}</p><p><strong>Message:</strong> {message}</p>"
            }
        ]
    }

    result = mailjet.send.create(data=mail_data)
    
    if result.status_code == 200:
        return jsonify({"message": "Email sent successfully!"}), 200
    else:
        return jsonify({"message": "Failed to send email."}), 500


if __name__ == '__main__':
    app.run(debug=True)"
"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Enhanced Flowchart Generator</title>
    <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;600&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/vis-network@9.1.2/dist/vis-network.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.waves.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
    <script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
    <style>
        .tooltip {
            position: absolute;
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 5px 10px;
            border-radius: 5px;
            font-size: 14px;
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.3s;
        }
        body, html {
            margin: 0;
            padding: 0;
            height: 100%;
            font-family: 'Raleway', sans-serif;
            background-color: rgba(26, 26, 46, 0.9);
            color: #ffffff;
            overflow: hidden;
        }

        #vanta-background {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -1;
        }

        .container {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            height: 100vh;
            padding: 20px;
            box-sizing: border-box;
        }

        h1 {
            font-size: 3.5rem;
            color: #e94560; 
            margin-bottom: 30px;
            text-align: center;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
        }

        .input-group {
            display: flex;
            flex-direction: column;
            align-items: center;
            width: 80%;
            max-width: 500px;
            margin-bottom: 20px;
        }

        input[type="text"], select, input[type="file"] {
            width: 100%;
            padding: 15px;
            border: none;
            border-radius: 50px;
            background-color: rgba(255, 255, 255, 0.2);
            color: #ffffff;
            font-size: 1.2rem;
            margin-bottom: 20px;
            transition: all 0.3s ease;
            backdrop-filter: blur(5px);
        }

        input[type="text"]:focus, select:focus {
            outline: none;
            box-shadow: 0 0 0 3px rgba(233, 69, 96, 0.5);
            transform: scale(1.05);
        }

        #generate-btn, #save-btn, #fullscreen-btn {
            background: linear-gradient(45deg, #e94560, #0f3460);
            color: #ffffff;
            padding: 15px 30px;
            border: none;
            border-radius: 50px;
            cursor: pointer;
            font-size: 1.2rem;
            font-weight: 600;
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
            margin: 0 10px;
        }

        #generate-btn:hover, #save-btn:hover, #fullscreen-btn:hover {
            transform: translateY(-3px) scale(1.05);
            box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
        }

        #flowchart-container {
            width: 90%;
            height: 70vh;
            background-color: rgba(255, 255, 255, 0.1);
            border-radius: 15px;
            margin-top: 30px;
            overflow: hidden;
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
            display: none;
            backdrop-filter: blur(5px);
            position: relative;
        }

        #flowchart {
            width: 100%;
            height: 100%;
        }

        #loading-animation {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            display: none;
        }

        .loader {
            border: 8px solid rgba(0, 0, 0, 0.1);
            border-radius: 50%;
            border-top: 8px solid #e94560;
            width: 80px;
            height: 80px;
            animation: spin 1.5s linear infinite;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        #error-message {
            color: #e94560;
            text-align: center;
            margin-top: 20px;
            display: none;
            font-weight: 600;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.3);
        }

        .fullscreen {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw !important;
            height: 100vh !important;
            z-index: 9999;
        }

        @media (max-width: 768px) {
            h1 {
                font-size: 2.5rem;
            }

            .input-group {
                width: 90%;
            }
        }
    </style>
</head>
<body>
    <div id="vanta-background"></div>
    <div class="container">
        <h1>Enhanced Flowchart Generator</h1>
        <div class="input-group">
            <input type="text" id="topic-input" placeholder="Enter topic or algorithm name" required>
            <select id="flowchart-type">
                <option value="standard">Standard Flowchart</option>
                <option value="process">Process Flowchart</option>
                <option value="decision">Decision Tree</option>
                <option value="swimlane">Swimlane Diagram</option>
            </select>
            <select id="flowchart-size">
                <option value="small">Small Flowchart</option>
                <option value="medium">Medium Flowchart</option>
                <option value="large">Detailed Flowchart</option>
            </select>
            <input type="file" id="file-input" accept=".pdf,.docx,.txt">
        </div>
        <div>
            <button id="generate-btn">Generate</button>
            <button id="save-btn" style="display:none;">Save as Image</button>
            <button id="fullscreen-btn" style="display:none;">Full Screen</button>
        </div>
        <div id="flowchart-container">
            <div id="flowchart"></div>
            <div id="loading-animation">
                <div class="loader"></div>
            </div>
        </div>
        <div id="error-message"></div>
    </div>

    <script>
        VANTA.WAVES({
            el: "#vanta-background",
            mouseControls: true,
            touchControls: true,
            gyroControls: false,
            minHeight: 200.00,
            minWidth: 200.00,
            scale: 1.00,
            scaleMobile: 1.00,
            color: 0x0f3460,
            shininess: 60.00,
            waveHeight: 20.00,
            waveSpeed: 1.50,
            zoom: 0.65
        })

        window.addEventListener('load', () => {
            gsap.from('h1', {duration: 1, y: -50, opacity: 0, ease: 'power3.out'});
            gsap.from('.input-group', {duration: 1, y: 50, opacity: 0, ease: 'power3.out', delay: 0.3});
            gsap.from('#generate-btn', {duration: 1, y: 50, opacity: 0, ease: 'power3.out', delay: 0.5});
        });

        document.getElementById('generate-btn').addEventListener('click', function () {
            var topic = document.getElementById('topic-input').value;
            var flowchartType = document.getElementById('flowchart-type').value;
            var flowchartSize = document.getElementById('flowchart-size').value;
            var fileInput = document.getElementById('file-input');
            
            gsap.to('#flowchart-container', {duration: 0.5, opacity: 1, display: 'block', ease: 'power2.inOut'});
            gsap.to('#loading-animation', {duration: 0.3, opacity: 1, display: 'block', ease: 'power2.inOut'});

            var formData = new FormData();
            formData.append('topic', topic);
            formData.append('flowchart_type', flowchartType);
            formData.append('flowchart_size', flowchartSize);
            if (fileInput.files.length > 0) {
                formData.append('file', fileInput.files[0]);
            }

            fetch('/get_flowchart_data', {
                method: 'POST',
                body: formData
            })
                .then(response => response.json())
                .then(data => {
                    gsap.to('#loading-animation', {duration: 0.3, opacity: 0, display: 'none', ease: 'power2.inOut'});
                    if (data.error) {
                        gsap.to('#error-message', {duration: 0.5, opacity: 1, display: 'block', text: "Error: " + data.error, ease: 'power2.inOut'});
                    } else {
                        gsap.to('#error-message', {duration: 0.3, opacity: 0, display: 'none', ease: 'power2.inOut'});
                        drawFlowchart(data, flowchartSize, flowchartType);
                        document.getElementById('save-btn').style.display = 'inline-block';
                        document.getElementById('fullscreen-btn').style.display = 'inline-block';
                    }
                });
        });

        function drawFlowchart(data, size, type) {
            var container = document.getElementById('flowchart');
            var nodes = new vis.DataSet(data.nodes);
            var edges = new vis.DataSet(data.edges);

            var options = {
                layout: {
                    hierarchical: {
                        direction: type === 'swimlane' ? 'LR' : 'TB',
                        sortMethod: 'directed',
                        nodeSpacing: 100,
                        levelSeparation: 150,
                    }
                },
                nodes: {
                    font: {
                        size: size === 'small' ? 14 : (size === 'medium' ? 16 : 18),
                        face: 'Raleway',
                        color: '#ffffff',
                        strokeWidth: 2,
                        strokeColor: '#000000',
                    },
                    borderWidth: 2,
                    borderWidthSelected: 4,
                    shadow: {
                        enabled: true,
                        color: 'rgba(0,0,0,0.5)',
                        size: 10,
                        x: 5,
                        y: 5
                    },
                    shapeProperties: {
                        borderRadius: 8
                    },
                    scaling: {
                        min: 20,
                        max: 60,
                        label: {
                            enabled: true,
                            min: 14,
                            max: 24,
                            maxVisible: 24,
                            drawThreshold: 5
                        }
                    },
                },
                edges: {
                    smooth: {
                        type: 'cubicBezier',
                        forceDirection: type === 'swimlane' ? 'horizontal' : 'vertical',
                        roundness: 0.5,
                    },
                    width: 2,
                    color: {
                        inherit: 'from'
                    },
                    shadow: {
                        enabled: true,
                        color: 'rgba(0,0,0,0.5)',
                        size: 10,
                        x: 5,
                        y: 5
                    },
                    arrows: {
                        to: { enabled: true, scaleFactor: 1, type: 'arrow' }
                    },
                    font: {
                        size: 12,
                        face: 'Raleway',
                        color: '#ffffff',
                        strokeWidth: 2,
                        strokeColor: '#000000',
                        align: 'horizontal',
                        background: 'none',
                    }
                },
                interaction: {
                    dragNodes: true,
                    dragView: true,
                    zoomView: true,
                    hover: true,
                    tooltipDelay: 100,
                    hideEdgesOnDrag: false,
                },
                physics: false, 
            };

            var network = new vis.Network(container, { nodes: nodes, edges: edges }, options);

            network.on("stabilizationIterationsDone", function () {
                network.setOptions( { physics: false } );
            });

             // Add hover effect and tooltip
             var tooltip = document.createElement('div');
             tooltip.className = 'tooltip';
             document.body.appendChild(tooltip);

             network.on("hoverNode", function (params) {
                var node = nodes.get(params.node);
                tooltip.textContent = node.label;
                tooltip.style.left = params.event.center.x + 'px';
                tooltip.style.top = params.event.center.y + 'px';
                tooltip.style.opacity = 1;
                gsap.to(node, {duration: 0.3, scale: 1.1, ease: 'power2.out'});
                nodes.update(node);
            });

            network.on("blurNode", function (params) {
                var node = nodes.get(params.node);
                tooltip.style.opacity = 0;
                gsap.to(node, {duration: 0.3, scale: 1, ease: 'power2.in'});
                nodes.update(node);
            });
            // Add zoom controls
            var zoomIn = document.createElement('button');
            zoomIn.textContent = '+';
            zoomIn.onclick = function() { network.moveTo({scale: network.getScale() * 1.2}); };
            
            var zoomOut = document.createElement('button');
            zoomOut.textContent = '-';
            zoomOut.onclick = function() { network.moveTo({scale: network.getScale() / 1.2}); };
            
            var zoomFit = document.createElement('button');
            zoomFit.textContent = 'Fit';
            zoomFit.onclick = function() { network.fit(); };
            
            var zoomControls = document.createElement('div');
            zoomControls.appendChild(zoomIn);
            zoomControls.appendChild(zoomOut);
            zoomControls.appendChild(zoomFit);
            zoomControls.style.position = 'absolute';
            zoomControls.style.top = '10px';
            zoomControls.style.right = '10px';
            container.appendChild(zoomControls);


            network.on("selectNode", function (params) {
                if (params.nodes.length === 1) {
                    var node = nodes.get(params.nodes[0]);
                    gsap.to(node, {duration: 0.3, scale: 1.2, ease: 'power2.out'});
                    nodes.update(node);
                }
            });

            network.on("deselectNode", function (params) {
                params.previousSelection.nodes.forEach(nodeId => {
                    var node = nodes.get(nodeId);
                    gsap.to(node, {duration: 0.3, scale: 1, ease: 'power2.in'});
                    nodes.update(node);
                });
            });
        }
        
        

        


        document.getElementById('save-btn').addEventListener('click', function() {
            html2canvas(document.getElementById('flowchart')).then(function(canvas) {
                var link = document.createElement('a');
                link.download = 'flowchart.png';
                link.href = canvas.toDataURL();
                link.click();
            });
        });

        document.getElementById('fullscreen-btn').addEventListener('click', function() {
            var elem = document.getElementById('flowchart-container');
            if (!document.fullscreenElement) {
                elem.requestFullscreen().catch(err => {
                    alert(`Error attempting to enable full-screen mode: ${err.message} (${err.name})`);
                });
            } else {
                document.exitFullscreen();
            }
        });

        document.addEventListener('fullscreenchange', function() {
            var elem = document.getElementById('flowchart-container');
            if (document.fullscreenElement) {
                elem.classList.add('fullscreen');
            } else {
                elem.classList.remove('fullscreen');
            }
        });


        // The following code was outside the drawFlowchart function and was causing issues
        // It's now placed within the function where it belongs for proper functionality.

        // var options = {
        //     // ... (other options)
        //     nodes: {
        //         // ... (other node options)
        //         tooltipDelay: 300,
        //         title: function(nodeData) {
        //             return nodeData.label;
        //         }
        //     }
        // };
    </script>
</body>
</html> 
"


the flowchart that is being generated is so worst and bad..i really need a best visually appealing flowchart that should be beautiful , colorful , modern , and amazing