Add telemetry dashboard and automatic server names; record Workshop 0.0.137
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
// Receipt times come from the receiver, never the game server's clock. A late
|
||||
// queued report is fresh receipt evidence, not proof that the server is online.
|
||||
export async function dashboardOverview(db, serverId) {
|
||||
const where = serverId ? ' WHERE server_id = ?' : '';
|
||||
const values = serverId ? [serverId] : [];
|
||||
const results = await db.batch([
|
||||
db.prepare(`SELECT COUNT(*) AS missions, COALESCE(SUM(outcome = 'victory'), 0) AS wins,
|
||||
COALESCE(SUM(outcome = 'defeat'), 0) AS losses, COALESCE(SUM(terminal = 0), 0) AS unfinished,
|
||||
COALESCE(SUM(partial), 0) AS partialMissions FROM missions${where}`).bind(...values),
|
||||
db.prepare(`SELECT COUNT(*) AS servers FROM servers${where}`).bind(...values),
|
||||
db.prepare(`SELECT COUNT(*) AS events, MAX(received_at) AS lastReceivedAt FROM events${where}`).bind(...values),
|
||||
db.prepare(`SELECT CASE WHEN terminal = 1 THEN outcome ELSE 'unfinished' END AS outcome,
|
||||
COUNT(*) AS missions FROM missions${where} GROUP BY terminal, outcome`).bind(...values),
|
||||
db.prepare(`SELECT lower(json_extract(payload, '$.terrain')) AS terrain, COUNT(*) AS missions,
|
||||
SUM(outcome = 'victory') AS wins, SUM(outcome = 'defeat') AS losses,
|
||||
SUM(terminal = 0) AS unfinished FROM missions${where}
|
||||
GROUP BY lower(json_extract(payload, '$.terrain')) ORDER BY missions DESC, terrain LIMIT 101`).bind(...values),
|
||||
]);
|
||||
const totals = {...results[0].results[0], ...results[1].results[0], ...results[2].results[0]};
|
||||
const completed = totals.wins + totals.losses;
|
||||
totals.winRate = completed ? Math.round(1000 * totals.wins / completed) / 10 : null;
|
||||
return {serverId, generatedAt: Math.floor(Date.now() / 1000), totals,
|
||||
outcomes: results[3].results, maps: results[4].results.slice(0, 100), mapsTruncated: results[4].results.length > 100};
|
||||
}
|
||||
|
||||
export async function dashboardServers(db, {limit, before}, query) {
|
||||
const result = await db.prepare(`WITH page AS (
|
||||
SELECT rowid AS cursor, * FROM servers WHERE rowid < ?
|
||||
AND (? = '' OR instr(lower(name), lower(?)) > 0 OR instr(server_id, lower(?)) > 0)
|
||||
ORDER BY rowid DESC LIMIT ?
|
||||
) SELECT s.cursor, s.server_id AS serverId, s.name, s.active, s.registration, s.created_at AS createdAt,
|
||||
e.received_at AS lastReceivedAt, json_extract(e.payload, '$.occurredAt') AS lastReportedAt,
|
||||
json_extract(e.payload, '$.type') AS lastEventType, e.mission_id AS lastMissionId,
|
||||
json_extract(e.payload, '$.terrain') AS terrain,
|
||||
json_extract(e.payload, '$.connectedPlayers') AS lastReportedPlayers,
|
||||
COUNT(m.id) AS missions, COALESCE(SUM(m.outcome = 'victory'), 0) AS wins,
|
||||
COALESCE(SUM(m.outcome = 'defeat'), 0) AS losses,
|
||||
COALESCE(SUM(m.terminal = 0), 0) AS unfinished, COALESCE(SUM(m.partial), 0) AS partialMissions
|
||||
FROM page s LEFT JOIN events e ON e.id = (
|
||||
SELECT id FROM events WHERE server_id = s.server_id ORDER BY received_at DESC, id DESC LIMIT 1)
|
||||
LEFT JOIN missions m ON m.server_id = s.server_id
|
||||
GROUP BY s.cursor ORDER BY s.cursor DESC`).bind(before, query, query, query, limit).all();
|
||||
return {servers: result.results, nextBefore: result.results.length === limit ? result.results.at(-1).cursor : null};
|
||||
}
|
||||
Reference in New Issue
Block a user