diff --git a/app/main.py b/app/main.py index 0635c72..58a56c8 100644 --- a/app/main.py +++ b/app/main.py @@ -1,5 +1,8 @@ from flask import Flask, request, Response, jsonify from flask_cors import CORS +from flask_socketio import SocketIO, join_room, emit +from collections import defaultdict +import time # Local imports from app from app.routes import session as session_route @@ -9,6 +12,7 @@ app = Flask(__name__) CORS(app) +socketio = SocketIO(app, cors_allowed_origins="*", async_mode="threading") # @app.route('/', methods=['GET']) # def welcome(): @@ -77,3 +81,50 @@ def batch_predict(): if request.method == 'POST': return session_route.batch_predict() return Response('Invalid request method for route', status=405, mimetype='application/json') + +# TODO: replace with persistent storage for replay & analytics +gaze_buffer = defaultdict(list) + +@socketio.on("join_session") +def handle_join(data): + session_id = data.get("session_id") + print("OBSERVER JOIN:", session_id, flush=True) + if session_id: + join_room(session_id) + emit("joined", {"session_id": session_id}) + + +@app.route("/api/session/gaze", methods=["POST"]) +def receive_gaze(): + data = request.get_json() + + if not data: + return Response("Invalid JSON", status=400) + + session_id = data.get("session_id") + x = data.get("x") + y = data.get("y") + timestamp = data.get("timestamp", time.time()) + + if not session_id or x is None or y is None: + return Response("Invalid payload", status=400) + + point = { + "session_id": session_id, + "x": x, + "y": y, + "timestamp": timestamp, + "phase": data.get("phase"), + } + + print("GAZE:", point, flush=True) + + # store for replay later + gaze_buffer[session_id].append(point) + socketio.emit("gaze_point", point, room=session_id) + + return jsonify({"status": "ok"}) + +if __name__ == "__main__": + socketio.run(app, host="0.0.0.0", port=5000) + diff --git a/app/requirements.txt b/app/requirements.txt index ba4582f..fb488f8 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -17,4 +17,5 @@ threadpoolctl==3.6.0 tzdata==2025.2 Werkzeug==3.1.3 gunicorn==23.0.0 -requests==2.31.0 \ No newline at end of file +requests==2.31.0 +flask-socketio==5.3.6 \ No newline at end of file