BookingEngine / app.py
ashutoshzade's picture
Update app.py
4c8cb10 verified
import gradio as gr
import os
import threading
from datetime import datetime, timedelta
from huggingface_hub import InferenceClient
ROWS = [chr(i) for i in range(ord("A"), ord("Z") + 1)]
SEATS_PER_ROW = 26
SECTION_RANGES = {
"left": range(1, 9),
"middle": range(9, 19),
"right": range(19, 27),
}
lock = threading.Lock()
seat_state = {row: {seat: "available" for seat in range(1, 27)} for row in ROWS}
holds = {}
bookings = {}
lock_owner = None
lock_expires_at = None
client = InferenceClient(
base_url="https://router.huggingface.co/v1",
token=os.getenv("HF_TOKEN")
)
def seat_label(row, seat):
return f"{row}{seat}"
def section_for_seat(seat):
if 1 <= seat <= 8:
return "left"
if 9 <= seat <= 18:
return "middle"
return "right"
def render_map():
html = """
<style>
.seat-grid { font-family: Arial, sans-serif; display: flex; flex-direction: column; gap: 6px; }
.row { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.row-label { width: 24px; font-weight: bold; }
.seat {
display: inline-block;
min-width: 34px;
padding: 6px 8px;
margin: 1px;
border-radius: 6px;
text-align: center;
color: white;
font-size: 12px;
}
.available { background: #2ecc71; }
.booked { background: #e74c3c; }
.held { background: #f39c12; }
.gap {
display: inline-block;
width: 18px;
}
</style>
<div class="seat-grid">
"""
for row in ROWS:
html += f'<div class="row"><span class="row-label">{row}</span>'
for seat in range(1, 27):
status = seat_state[row][seat]
cls = "available" if status == "available" else "booked" if status == "booked" else "held"
html += f'<span class="seat {cls}">{seat}</span>'
if seat in (8, 18):
html += '<span class="gap"></span>'
html += "</div>"
html += "</div>"
return html
def available_seats():
out = []
for row in ROWS:
for seat in range(1, 27):
if seat_state[row][seat] == "available":
out.append(seat_label(row, seat))
return out
def find_best_block(n):
for row in ROWS:
for section_name, seats in SECTION_RANGES.items():
seats = list(seats)
run = []
for s in seats:
if seat_state[row][s] == "available":
run.append(s)
if len(run) >= n:
return [seat_label(row, x) for x in run[:n]]
else:
run = []
return None
def acquire_lock(user_id):
global lock_owner, lock_expires_at
now = datetime.utcnow()
if lock_owner and lock_expires_at and now < lock_expires_at and lock_owner != user_id:
return False, f"Locked by {lock_owner}"
lock_owner = user_id
lock_expires_at = now + timedelta(minutes=10)
return True, f"Lock granted to {user_id}"
def release_lock(user_id):
global lock_owner, lock_expires_at
with lock:
if lock_owner != user_id:
return f"You do not own the lock."
lock_owner = None
lock_expires_at = None
return "Lock released."
def hold_seats(user_id, count):
with lock:
ok, msg = acquire_lock(user_id)
if not ok:
return render_map(), msg, "", ""
seats = find_best_block(count)
if not seats:
return render_map(), "Not enough adjacent seats available.", "", ""
hold_id = f"H{len(holds)+1}"
for seat in seats:
row = seat[0]
num = int(seat[1:])
seat_state[row][num] = "held"
holds[hold_id] = {
"user_id": user_id,
"seats": seats,
"expires_at": datetime.utcnow() + timedelta(minutes=5),
}
return render_map(), f"Hold created: {hold_id}", hold_id, ", ".join(seats)
def confirm_hold(user_id, hold_id):
global lock_owner, lock_expires_at
with lock:
h = holds.get(hold_id)
if not h:
return render_map(), "Hold not found.", ""
if h["user_id"] != user_id:
return render_map(), "You do not own this hold.", ""
for seat in h["seats"]:
row = seat[0]
num = int(seat[1:])
seat_state[row][num] = "booked"
booking_id = f"B{len(bookings)+1}"
bookings[booking_id] = h
del holds[hold_id]
lock_owner = None
lock_expires_at = None
return render_map(), f"Confirmed. Booking ID: {booking_id}. Seats: {', '.join(h['seats'])}", ", ".join(h["seats"])
def ai_chat(message, history):
messages = [{"role": "system", "content": "You are a ticketing assistant for a venue seat booking app."}]
for user_msg, bot_msg in history:
messages.append({"role": "user", "content": user_msg})
messages.append({"role": "assistant", "content": bot_msg})
messages.append({"role": "user", "content": message})
if os.getenv("HF_TOKEN"):
resp = client.chat.completions.create(
model="meta-llama/Llama-3.1-8B-Instruct",
messages=messages,
max_tokens=200,
temperature=0.2,
)
return resp.choices[0].message.content
return "HF_TOKEN is not configured."
def hold_action(user_id, group_size):
return hold_seats(user_id, int(group_size))
def confirm_action(user_id, hold_id):
return confirm_hold(user_id, hold_id)
def release_action(user_id):
msg = release_lock(user_id)
return render_map(), msg
with gr.Blocks() as demo:
gr.Markdown("# Venue Ticketing System")
with gr.Row():
user_id = gr.Textbox(label="User ID", value="user1")
group_size = gr.Number(label="Seats needed", value=2, precision=0)
with gr.Row():
btn_hold = gr.Button("Hold Seats")
btn_confirm = gr.Button("Confirm Booking")
btn_release = gr.Button("Release Lock")
with gr.Row():
hold_id = gr.Textbox(label="Hold ID")
seats_text = gr.Textbox(label="Seats", interactive=False)
status = gr.Textbox(label="Status", interactive=False)
seat_map = gr.HTML(label="Seat Map")
ai = gr.ChatInterface(fn=ai_chat, title="AI Assistant")
btn_hold.click(
hold_action,
inputs=[user_id, group_size],
outputs=[seat_map, status, hold_id, seats_text],
)
btn_confirm.click(
confirm_action,
inputs=[user_id, hold_id],
outputs=[seat_map, status, seats_text],
)
btn_release.click(
release_action,
inputs=[user_id],
outputs=[seat_map, status],
)
demo.load(render_map, outputs=seat_map)
demo.queue(default_concurrency_limit=1)
demo.launch()