Files
grepo-remote/future_ideas.md
2026-05-03 22:25:30 +03:00

5.2 KiB

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):

// 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(); 
    }
}
# 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.
window.addEventListener('beforeunload', () => {
    if (typeof es !== 'undefined' && es !== null) {
        es.close();
    }
});
  1. Server-side (tracker.py): Ensure the generator handles client disconnects gracefully and immediately cleans up the subscriber queue without waiting for a timeout.
# Make sure the generator yields spaces/heartbeats actively so the OS 
# throws an IOError/GeneratorExit the moment the client drops.