full scoreboard update

This commit is contained in:
ilyastar9999
2025-12-03 10:56:33 +03:00
parent c5bcfab44c
commit ac332ab845
4 changed files with 81 additions and 4 deletions

View File

@@ -9,10 +9,12 @@ SECRET_TOKEN=asdasdasd
# Services Directory (where managed services will be stored)
SERVICES_DIR=/root/services
# Scoreboard Configuration
# Scoreboard Configuration (ForcAD uses Socket.IO)
SCOREBOARD_URL=http://94.228.113.149:8080
USE_SOCKETIO=true
USE_HTTP_POLLING=false
SCOREBOARD_WS_URL=ws://10.60.0.1:8080/api/events
SCOREBOARD_API_URL=http://10.60.0.1:8080/api
USE_HTTP_POLLING=false
POLLING_INTERVAL=10
OUR_TEAM_ID=1
ALERT_THRESHOLD_POINTS=100

View File

@@ -48,9 +48,11 @@ services:
environment:
DATABASE_URL: postgresql://${POSTGRES_USER:-adctrl}:${POSTGRES_PASSWORD:-adctrl_secure_password}@postgres:5432/${POSTGRES_DB:-adctrl}
SECRET_TOKEN: ${SECRET_TOKEN}
SCOREBOARD_URL: ${SCOREBOARD_URL:-http://10.60.0.1:8080}
USE_SOCKETIO: ${USE_SOCKETIO:-true}
USE_HTTP_POLLING: ${USE_HTTP_POLLING:-false}
SCOREBOARD_WS_URL: ${SCOREBOARD_WS_URL:-ws://10.60.0.1:8080/api/events}
SCOREBOARD_API_URL: ${SCOREBOARD_API_URL:-http://10.60.0.1:8080/api}
USE_HTTP_POLLING: ${USE_HTTP_POLLING:-false}
POLLING_INTERVAL: ${POLLING_INTERVAL:-10}
OUR_TEAM_ID: ${OUR_TEAM_ID:-1}
ALERT_THRESHOLD_POINTS: ${ALERT_THRESHOLD_POINTS:-100}

View File

@@ -8,6 +8,7 @@ import asyncio
from datetime import datetime, timedelta
from typing import Optional, Dict, Any
import aiohttp
import socketio
from fastapi import FastAPI, HTTPException, Depends, Header
from pydantic import BaseModel
import asyncpg
@@ -16,9 +17,11 @@ from contextlib import asynccontextmanager
# Configuration
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://adctrl:adctrl@postgres:5432/adctrl")
SECRET_TOKEN = os.getenv("SECRET_TOKEN", "change-me-in-production")
SCOREBOARD_URL = os.getenv("SCOREBOARD_URL", "http://10.60.0.1:8080") # Base URL for Socket.IO
SCOREBOARD_WS_URL = os.getenv("SCOREBOARD_WS_URL", "ws://scoreboard:8080/api/events")
SCOREBOARD_API_URL = os.getenv("SCOREBOARD_API_URL", "http://10.60.0.1:8080/api")
USE_HTTP_POLLING = os.getenv("USE_HTTP_POLLING", "false").lower() == "true"
USE_SOCKETIO = os.getenv("USE_SOCKETIO", "true").lower() == "true" # Use Socket.IO by default
POLLING_INTERVAL = int(os.getenv("POLLING_INTERVAL", "10")) # seconds
OUR_TEAM_ID = int(os.getenv("OUR_TEAM_ID", "1"))
ALERT_THRESHOLD_POINTS = float(os.getenv("ALERT_THRESHOLD_POINTS", "100"))
@@ -272,6 +275,69 @@ async def http_polling_listener():
await asyncio.sleep(POLLING_INTERVAL)
async def socketio_listener():
"""Listen to ForcAD scoreboard using Socket.IO"""
sio = socketio.AsyncClient(logger=False, engineio_logger=False)
@sio.event(namespace='/game_events')
async def update_scoreboard(data):
"""Handle scoreboard update events"""
try:
event_data = data.get('data', {})
round_num = event_data.get('round', 0)
team_tasks = event_data.get('team_tasks', [])
print(f"📊 Round {round_num} - Processing {len(team_tasks)} team updates")
for team_task in team_tasks:
team_id = team_task.get('team_id')
task_id = team_task.get('task_id')
stolen = team_task.get('stolen', 0)
lost = team_task.get('lost', 0)
if team_id == OUR_TEAM_ID and (stolen > 0 or lost > 0):
print(f" Team {team_id} Task {task_id}: stolen={stolen}, lost={lost}")
except Exception as e:
print(f"Error processing update_scoreboard: {e}")
@sio.event(namespace='/game_events')
async def init_scoreboard(data):
"""Handle initial scoreboard data"""
try:
print("📡 Received initial scoreboard data")
event_data = data.get('data', {})
teams = event_data.get('teams', [])
tasks = event_data.get('tasks', [])
print(f" Teams: {', '.join([f\"{t.get('name')} (ID:{t.get('id')})\" for t in teams])}")
print(f" Tasks: {', '.join([t.get('name') for t in tasks])}")
except Exception as e:
print(f"Error processing init_scoreboard: {e}")
@sio.event
async def connect():
print("✅ Connected to ForcAD scoreboard Socket.IO")
@sio.event
async def disconnect():
print("❌ Disconnected from scoreboard")
while True:
try:
print(f"Connecting to {SCOREBOARD_URL}/socket.io ...")
await sio.connect(
SCOREBOARD_URL,
namespaces=['/game_events'],
transports=['websocket']
)
await sio.wait()
except Exception as e:
print(f"Socket.IO error: {e}")
print("Reconnecting in 5 seconds...")
await asyncio.sleep(5)
async def websocket_listener():
"""Listen to scoreboard WebSocket for events"""
reconnect_delay = 5
@@ -336,8 +402,14 @@ async def lifespan(app: FastAPI):
global db_pool, ws_task
db_pool = await asyncpg.create_pool(DATABASE_URL, min_size=2, max_size=10)
print(f"Our team ID: {OUR_TEAM_ID}")
# Start listener based on configuration
if USE_HTTP_POLLING:
if USE_SOCKETIO:
print(f"Starting Socket.IO mode")
print(f"Scoreboard URL: {SCOREBOARD_URL}")
ws_task = asyncio.create_task(socketio_listener())
elif USE_HTTP_POLLING:
print(f"Starting HTTP polling mode (interval: {POLLING_INTERVAL}s)")
print(f"Scoreboard API: {SCOREBOARD_API_URL}")
ws_task = asyncio.create_task(http_polling_listener())

View File

@@ -4,3 +4,4 @@ asyncpg==0.29.0
pydantic==2.5.3
aiohttp==3.9.1
python-dotenv==1.0.0
python-socketio[asyncio_client]==5.11.0