# Future Ideas & Optimizations This document tracks potential architectural improvements and features inspired by other Grepolis alliance coordination scripts (like GrepoData and Noct). ## 1. Timestamp-Based Polling Optimization (`since` parameter) **Inspired by:** `noct-api.grepo-soft.workers.dev` **Current State:** The Tampermonkey client polls the server every 8-18 seconds and receives the full state/command payload every time, even if nothing has changed. **Proposed Implementation:** - Add a `since` timestamp parameter to the client's poll requests. - The server checks if any commands or state updates have occurred *after* the `since` timestamp. - **If no new data:** The server returns an empty `HTTP 204 No Content` response. - **If new data:** The server returns `HTTP 200 OK` with only the data that changed. **Benefits:** - Drastically reduces server bandwidth and CPU load. - Minimizes the size of network requests on the client side, making the script stealthier and less resource-intensive in the browser. **Concrete Code Example (How Noct does it):** ```javascript // 1. Client-side polling logic let lastFetchTime = Date.now(); async function pollCommands() { const url = `https://noct-api.grepo-soft.workers.dev/api/alliance/commands` + `?alliance=p0PmzsZMo4xZ2o29uvqggy5d` + `&world=gr118` + `&clientId=848938473` + `&since=${lastFetchTime}`; // Ask only for things after this timestamp const response = await fetch(url); // 2. Server returns HTTP 204 (No Content) if nothing new happened if (response.status === 204) { return; // Empty payload, exit early } // 3. Server returns HTTP 200 (OK) only if there are NEW commands if (response.status === 200) { const data = await response.json(); // Process new commands... executeCommands(data.commands); // Update the timestamp so the next poll only asks for things after this moment lastFetchTime = Date.now(); } } ``` ```python # Backend (Python/Flask Equivalent) @app.route('/api/alliance/commands') def get_commands(): # Get the timestamp from the URL query since_ts = int(request.args.get('since', 0)) # Query DB for commands created AFTER the 'since' timestamp new_commands = db.execute( "SELECT * FROM commands WHERE created_at_ts > ?", (since_ts,) ).fetchall() if not new_commands: # Return empty body with 204 No Content return '', 204 return jsonify({"commands": new_commands}), 200 ``` ## 2. WebSocket Architecture for Real-Time Synchronization **Inspired by:** `grepodata.com` (ReactPHP WebSocket server) **Current State:** Command delivery relies on HTTP polling. If an attack plan requires a launch in 30 seconds, but the client is on an 18-second polling interval, there is a high risk of missing the execution window or executing late. **Proposed Implementation:** - Integrate `Flask-SocketIO` (or a standalone async WebSocket server) into the backend. - The client script establishes a persistent `wss://` connection upon loading the game. - The client authenticates using its `clan_key` and subscribes to its alliance "topic/room". - When an admin arms an attack plan or a player updates their town state, the server instantly *pushes* the payload to all connected alliance members. **Benefits:** - **Zero Polling Latency:** Commands arrive in ~100ms instead of 8-18 seconds. - **Perfect Attack Timing:** Ensures clients receive armed plans immediately, maximizing the margin for precise execution. - **Instant UI Updates:** The dashboard and attack planner can update in real-time as members come online or troop counts change. ## 3. Server-Sent Events (SSE) Lag/Refresh Bug Fix **Issue:** When refreshing or hitting the "back" button on the Live Tracker (`tracker.html`), the page occasionally hangs, lags heavily, or completely fails to load. **Root Cause:** The Live Tracker uses SSE (`EventSource`) to receive real-time movement updates. Modern browsers strictly limit simultaneous HTTP/1.1 connections to the same server (usually 6 maximum). When the user navigates away or refreshes, the browser drops the frontend page, but the Python/Flask backend (`tracker.py`) does not immediately detect the broken pipe and keeps the socket open, waiting to send data. If the user hits refresh multiple times, these "ghost" connections stack up. Upon reaching 6 ghost connections, the browser refuses to load any further requests until the old connections naturally time out (which can take 30+ seconds). **Proposed Fix:** 1. **Client-side (`tracker.html`)**: Ensure the browser explicitly tells the server the connection is closing exactly as the page unloads. ```javascript window.addEventListener('beforeunload', () => { if (typeof es !== 'undefined' && es !== null) { es.close(); } }); ``` 2. **Server-side (`tracker.py`)**: Ensure the generator handles client disconnects gracefully and immediately cleans up the subscriber queue without waiting for a timeout. ```python # Make sure the generator yields spaces/heartbeats actively so the OS # throws an IOError/GeneratorExit the moment the client drops. ```