maze-generator / app.py
utarn's picture
Add docker compose
a613a86
#!/usr/bin/env python3
import gradio as gr
import os
import threading
import sys
import uuid
import time
from main import generate_multiple_mazes, merge_pdfs
# Session management
user_sessions = {}
def create_session():
"""Create a new session for the user"""
session_id = str(uuid.uuid4())[:8] # Short session ID
user_sessions[session_id] = {
'created_at': time.time(),
'files_generated': 0
}
return session_id
def get_session_files(session_id):
"""Get list of PDF files for a specific session"""
try:
if os.path.exists('pdfs'):
pdf_files = [f for f in os.listdir('pdfs')
if f.endswith('.pdf') and f.startswith(f"{session_id}_")]
pdf_files.sort()
return pdf_files if pdf_files else ["No PDF files found for this session"]
else:
return ["pdfs/ directory does not exist"]
except Exception as e:
return [f"Error: {str(e)}"]
def cleanup_merged_pdf(session_id):
"""Remove the merged PDF for a session after download"""
merged_pdf_path = os.path.join('pdfs', f"{session_id}_merged_mazes.pdf")
if os.path.exists(merged_pdf_path):
try:
os.remove(merged_pdf_path)
print(f"Cleaned up merged PDF: {merged_pdf_path}")
except Exception as e:
print(f"Error cleaning up merged PDF: {e}")
def generate_mazes_interface(num_files, width, height, session_id, progress=gr.Progress()):
"""Interface function for generating mazes with progress tracking"""
try:
progress(0.1, desc="Starting maze generation...")
# Validate parameters
if num_files < 1:
return "Error: Number of files must be at least 1", None
if not (2 <= width <= 200):
return "Error: Width must be between 2 and 200", None
if not (2 <= height <= 200):
return "Error: Height must be between 2 and 200", None
progress(0.2, desc="Generating mazes...")
# Generate the mazes with session ID
success_count = generate_multiple_mazes(num_files, width, height, session_id)
progress(1.0, desc="Generation complete!")
# Update session info
if session_id in user_sessions:
user_sessions[session_id]['files_generated'] += success_count
if success_count == num_files:
return f"Successfully generated {success_count} maze PDFs for session {session_id}", get_session_files(session_id)
else:
return f"Warning: Only {success_count} out of {num_files} mazes were generated successfully for session {session_id}", get_session_files(session_id)
except Exception as e:
return f"Error: {str(e)}", None
def merge_pdfs_interface(session_id, progress=gr.Progress()):
"""Interface function for merging PDFs with progress tracking"""
try:
progress(0.1, desc="Starting PDF merge...")
if not os.path.exists('pdfs'):
return "Error: pdfs/ directory does not exist", None, None
progress(0.5, desc="Merging PDFs...")
# Merge only session-specific PDFs
success = merge_pdfs('pdfs', session_id)
progress(1.0, desc="Merge complete!")
if success:
merged_pdf_path = os.path.join('pdfs', f"{session_id}_merged_mazes.pdf")
if os.path.exists(merged_pdf_path):
return f"Successfully merged session {session_id} PDFs into {session_id}_merged_mazes.pdf", get_session_files(session_id), merged_pdf_path
else:
return "Merge completed but merged file not found", get_session_files(session_id), None
else:
return "Failed to merge PDFs", get_session_files(session_id), None
except Exception as e:
return f"Error: {str(e)}", None, None
def get_pdf_list():
"""Get list of PDF files in pdfs directory"""
try:
if os.path.exists('pdfs'):
pdf_files = [f for f in os.listdir('pdfs') if f.endswith('.pdf')]
pdf_files.sort()
return pdf_files if pdf_files else ["No PDF files found"]
else:
return ["pdfs/ directory does not exist"]
except Exception as e:
return [f"Error: {str(e)}"]
def refresh_file_list():
"""Refresh the file list"""
return get_pdf_list()
def create_interface():
"""Create the Gradio interface"""
# Create pdfs directory if it doesn't exist
os.makedirs('pdfs', exist_ok=True)
with gr.Blocks(title="Maze Generator", theme=gr.themes.Soft()) as interface:
# Session state
session_id = gr.State(create_session())
gr.Markdown("# 🎯 Maze Generator")
gr.Markdown("Generate custom maze PDFs or merge existing ones using this web interface.")
gr.Markdown(f"**Session ID:** {session_id.value} - Your files are isolated from other users")
with gr.Tabs():
with gr.TabItem("Generate Mazes"):
with gr.Row():
with gr.Column():
gr.Markdown("### Generate New Mazes")
num_files = gr.Number(
label="Number of Mazes",
value=1,
minimum=1,
maximum=50,
step=1
)
width = gr.Number(
label="Width (cells)",
value=25,
minimum=2,
maximum=200,
step=1
)
height = gr.Number(
label="Height (cells)",
value=35,
minimum=2,
maximum=200,
step=1
)
generate_btn = gr.Button("πŸš€ Generate Mazes", variant="primary", size="lg")
with gr.Column():
gr.Markdown("### Your Generated Files")
file_list = gr.List(
label="PDF Files for Your Session",
value=get_session_files(session_id.value)
)
refresh_btn = gr.Button("πŸ”„ Refresh List", size="sm")
generate_output = gr.Textbox(
label="Status",
lines=3,
max_lines=5,
show_label=False,
container=True
)
# Event handlers
generate_btn.click(
fn=generate_mazes_interface,
inputs=[num_files, width, height, session_id],
outputs=[generate_output, file_list],
show_progress=True
)
refresh_btn.click(
fn=lambda sid: get_session_files(sid),
inputs=[session_id],
outputs=[file_list]
)
with gr.TabItem("Merge PDFs"):
with gr.Row():
with gr.Column():
gr.Markdown("### Merge Your PDFs")
gr.Markdown("Merge all your PDF files in this session into a single file. Individual files will be deleted after merging.")
merge_btn = gr.Button("πŸ”— Merge Your PDFs", variant="primary", size="lg")
merge_output = gr.Textbox(
label="Merge Status",
lines=3,
max_lines=5,
show_label=False,
container=True
)
merge_file_list = gr.List(
label="Your PDF Files After Merge",
value=get_session_files(session_id.value)
)
download_merged_btn = gr.DownloadButton(
label="πŸ“₯ Download Merged PDF",
variant="secondary",
size="lg"
)
# Event handlers
merge_btn.click(
fn=merge_pdfs_interface,
inputs=[session_id],
outputs=[merge_output, merge_file_list, download_merged_btn],
show_progress=True
)
# Clean up merged PDF after download
download_merged_btn.click(
fn=lambda sid: cleanup_merged_pdf(sid),
inputs=[session_id]
)
# Auto-refresh file list every few seconds
interface.load(
fn=lambda sid: (get_session_files(sid), get_session_files(sid)),
inputs=[session_id],
outputs=[file_list, merge_file_list]
)
return interface
if __name__ == "__main__":
print("πŸš€ Starting Maze Generator Application...")
print("πŸ“ Creating pdfs directory if it doesn't exist...")
# Create and launch the interface
interface = create_interface()
print("🌐 Launching Gradio interface...")
print("πŸ“ Server will be available at: http://0.0.0.0:7861")
print("πŸ“ Local access: http://localhost:7861")
print("⏳ Waiting for server to start...")
interface.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)
print("βœ… Maze Generator is ready and running!")
print("🎯 Open your browser and navigate to http://localhost:7860")