asd
This commit is contained in:
13
init-db.sql
13
init-db.sql
@@ -32,6 +32,17 @@ CREATE TABLE IF NOT EXISTS scoreboard_state (
|
||||
UNIQUE(team_id, service_name)
|
||||
);
|
||||
|
||||
-- Team scores table - track total and flag points over time
|
||||
CREATE TABLE IF NOT EXISTS team_scores (
|
||||
id SERIAL PRIMARY KEY,
|
||||
team_id INTEGER NOT NULL,
|
||||
team_name VARCHAR(255) NOT NULL,
|
||||
total_score FLOAT DEFAULT 0,
|
||||
flag_points FLOAT DEFAULT 0,
|
||||
round INTEGER NOT NULL,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Attacks tracking table for scoreboard injector
|
||||
CREATE TABLE IF NOT EXISTS attacks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
@@ -84,6 +95,8 @@ ON CONFLICT (key) DO NOTHING;
|
||||
|
||||
-- Create indexes for performance
|
||||
CREATE INDEX IF NOT EXISTS idx_scoreboard_state_team_service ON scoreboard_state(team_id, service_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_team_scores_round ON team_scores(round);
|
||||
CREATE INDEX IF NOT EXISTS idx_team_scores_team_id ON team_scores(team_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_attacks_timestamp ON attacks(timestamp);
|
||||
CREATE INDEX IF NOT EXISTS idx_attacks_our_attack ON attacks(is_our_attack);
|
||||
CREATE INDEX IF NOT EXISTS idx_attacks_attack_to_us ON attacks(is_attack_to_us);
|
||||
|
||||
@@ -189,8 +189,9 @@ async def socketio_listener():
|
||||
"""Listen to ForcAD scoreboard using Socket.IO"""
|
||||
sio = socketio.AsyncClient(logger=False, engineio_logger=False)
|
||||
|
||||
# Cache for task names
|
||||
# Cache for task and team names
|
||||
task_names = {}
|
||||
team_names = {}
|
||||
|
||||
@sio.event(namespace='/game_events')
|
||||
async def update_scoreboard(data):
|
||||
@@ -200,11 +201,20 @@ async def socketio_listener():
|
||||
round_num = event_data.get('round', 0)
|
||||
round_start = event_data.get('round_start', 0)
|
||||
team_tasks = event_data.get('team_tasks', [])
|
||||
teams_data = event_data.get('teams', [])
|
||||
|
||||
print(f"📊 Round {round_num} - Processing {len(team_tasks)} team updates")
|
||||
|
||||
conn = await db_pool.acquire()
|
||||
try:
|
||||
# Store team scores
|
||||
for team in teams_data:
|
||||
team_id = team.get('id')
|
||||
await conn.execute("""
|
||||
INSERT INTO team_scores (team_id, team_name, total_score, flag_points, round, timestamp)
|
||||
VALUES ($1, $2, $3, $4, $5, NOW())
|
||||
""", team_id, team_names.get(team_id, f'Team {team_id}'),
|
||||
team.get('score', 0), team.get('flag_points', 0), round_num)
|
||||
for team_task in team_tasks:
|
||||
team_id = team_task.get('team_id')
|
||||
task_id = team_task.get('task_id')
|
||||
@@ -294,6 +304,10 @@ async def socketio_listener():
|
||||
for task in tasks:
|
||||
task_names[task.get('id')] = task.get('name')
|
||||
|
||||
# Cache team names
|
||||
for team in teams:
|
||||
team_names[team.get('id')] = team.get('name')
|
||||
|
||||
team_names_str = ', '.join([f"{t.get('name')} (ID:{t.get('id')})" for t in teams])
|
||||
task_names_str = ', '.join([t.get('name') for t in tasks])
|
||||
print(f" Teams: {team_names_str}")
|
||||
@@ -390,25 +404,42 @@ async def get_stats():
|
||||
|
||||
@app.get("/attacks", dependencies=[Depends(verify_token)])
|
||||
async def get_attacks(limit: int = 100, our_attacks: Optional[bool] = None, attacks_to_us: Optional[bool] = None):
|
||||
"""Get recent attacks"""
|
||||
"""Get recent attacks with team names"""
|
||||
conn = await get_db()
|
||||
try:
|
||||
query = "SELECT * FROM attacks WHERE 1=1"
|
||||
query = """
|
||||
SELECT
|
||||
a.*,
|
||||
ts_attacker.team_name as attacker_team_name,
|
||||
ts_victim.team_name as victim_team_name
|
||||
FROM attacks a
|
||||
LEFT JOIN (
|
||||
SELECT DISTINCT ON (team_id) team_id, team_name
|
||||
FROM team_scores
|
||||
ORDER BY team_id, timestamp DESC
|
||||
) ts_attacker ON a.attacker_team_id = ts_attacker.team_id
|
||||
LEFT JOIN (
|
||||
SELECT DISTINCT ON (team_id) team_id, team_name
|
||||
FROM team_scores
|
||||
ORDER BY team_id, timestamp DESC
|
||||
) ts_victim ON a.victim_team_id = ts_victim.team_id
|
||||
WHERE 1=1
|
||||
"""
|
||||
params = []
|
||||
param_count = 0
|
||||
|
||||
if our_attacks is not None:
|
||||
param_count += 1
|
||||
query += f" AND is_our_attack = ${param_count}"
|
||||
query += f" AND a.is_our_attack = ${param_count}"
|
||||
params.append(our_attacks)
|
||||
|
||||
if attacks_to_us is not None:
|
||||
param_count += 1
|
||||
query += f" AND is_attack_to_us = ${param_count}"
|
||||
query += f" AND a.is_attack_to_us = ${param_count}"
|
||||
params.append(attacks_to_us)
|
||||
|
||||
param_count += 1
|
||||
query += f" ORDER BY timestamp DESC LIMIT ${param_count}"
|
||||
query += f" ORDER BY a.timestamp DESC LIMIT ${param_count}"
|
||||
params.append(limit)
|
||||
|
||||
rows = await conn.fetch(query, *params)
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<th>Attacker</th>
|
||||
<th>Victim</th>
|
||||
<th>Service</th>
|
||||
<th>Points</th>
|
||||
<th>Flags</th>
|
||||
<th>Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -126,13 +126,16 @@
|
||||
typeLabel = '<span class="badge bg-danger">Against Us</span>';
|
||||
}
|
||||
|
||||
const attackerName = attack.attacker_team_id ? (attack.attacker_team_name || `Team ${attack.attacker_team_id}`) : 'Unknown';
|
||||
const victimName = attack.victim_team_id ? (attack.victim_team_name || `Team ${attack.victim_team_id}`) : 'Unknown';
|
||||
|
||||
html += `
|
||||
<tr>
|
||||
<td>${new Date(attack.timestamp).toLocaleString()}</td>
|
||||
<td>Team ${attack.attacker_team_id}</td>
|
||||
<td>Team ${attack.victim_team_id}</td>
|
||||
<td>${attackerName}</td>
|
||||
<td>${victimName}</td>
|
||||
<td>${attack.service_name}</td>
|
||||
<td>${attack.points ? attack.points.toFixed(2) : '-'}</td>
|
||||
<td>${attack.points ? Math.round(attack.points) : '-'}</td>
|
||||
<td>${typeLabel}</td>
|
||||
</tr>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user