diff --git a/src/api/routes/analytics.ts b/src/api/routes/analytics.ts index 65a0bf4..d060922 100644 --- a/src/api/routes/analytics.ts +++ b/src/api/routes/analytics.ts @@ -1,85 +1,85 @@ -import { INFLUXDB_BUCKET, InfluxQueryAPI } from "../.."; -import { formatString } from "../../utils/stringUtils"; -import { parseTimeToMilliseconds } from "../../utils/timeUtils"; - -// Query to get the player count history for tge last 24 hours in 1 hour intervals -const getPlayerHistoryQuery = `from(bucket: "${INFLUXDB_BUCKET}") - |> range(start: -{}) - |> filter(fn: (r) => r["_measurement"] == "scoresaber") - |> filter(fn: (r) => r["_field"] == "value") - |> filter(fn: (r) => r["type"] == "player_count") - |> aggregateWindow(every: {}, fn: mean) - |> yield() -`; - -const getScoreCountHistoryQuery = `from(bucket: "${INFLUXDB_BUCKET}") - |> range(start: -{}) - |> filter(fn: (r) => r["_measurement"] == "scoresaber") - |> filter(fn: (r) => r["_field"] == "value") - |> filter(fn: (r) => r["type"] == "score_count") - |> aggregateWindow(every: {}, fn: spread, createEmpty: true) -`; - -export default function analyticsRoute(app: any) { - app.get("/analytics", async (req: any, res: any) => { - const before = new Date().getTime(); - - const timeQuery = req.query.time || "30d"; - const timeInMs = parseTimeToMilliseconds(timeQuery.toString()); - if (timeInMs > 30 * 24 * 60 * 60 * 1000) { - return res.status(400).json({ - error: "Time range too large. Max time range is 30 days.", - }); - } - const shouldUseLongerIntervals = timeInMs > 24 * 60 * 60 * 1000 * 7; // 7 days - - const getActivePlayersHistory = async () => { - const rows = await InfluxQueryAPI.collectRows( - formatString( - getPlayerHistoryQuery, - false, - timeQuery, - shouldUseLongerIntervals ? "1d" : "1h" - ) - ); - let history = rows.map((row: any) => ({ - time: row._time, - value: row._value !== null ? row._value.toFixed(0) : null, - })); - return history.sort( - (a: any, b: any) => - new Date(a.time).getTime() - new Date(b.time).getTime() - ); - }; - - const getScoreCountHistory = async () => { - const rows = await InfluxQueryAPI.collectRows( - formatString( - getScoreCountHistoryQuery, - false, - timeQuery, - shouldUseLongerIntervals ? "1d" : "1h" - ) - ); - let history = rows.map((row: any) => ({ - time: row._time, - value: row._value !== null ? row._value.toFixed(0) : null, - })); - return history.sort( - (a: any, b: any) => - new Date(a.time).getTime() - new Date(b.time).getTime() - ); - }; - - const [activePlayersHistory, scoreCountHistory] = await Promise.all([ - getActivePlayersHistory(), - getScoreCountHistory(), - ]); - - return res.json({ - serverTimeTaken: new Date().getTime() - before + "ms", - activePlayersHistory, - scoreCountHistory, - }); - }); -} +import { INFLUXDB_BUCKET, InfluxQueryAPI } from "../.."; +import { formatString } from "../../utils/stringUtils"; +import { parseTimeToMilliseconds } from "../../utils/timeUtils"; + +// Query to get the player count history for tge last 24 hours in 1 hour intervals +const getPlayerHistoryQuery = `from(bucket: "${INFLUXDB_BUCKET}") +|> range(start: -{}) +|> filter(fn: (r) => r["_measurement"] == "scoresaber") +|> filter(fn: (r) => r["type"] == "score") +|> filter(fn: (r) => r["_field"] == "player_id") +|> unique() +|> aggregateWindow(every: {}, fn: count) +`; + +const getScoreCountHistoryQuery = `from(bucket: "${INFLUXDB_BUCKET}") + |> range(start: -{}) + |> filter(fn: (r) => r["_measurement"] == "scoresaber") + |> filter(fn: (r) => r["_field"] == "value") + |> filter(fn: (r) => r["type"] == "score_count") + |> aggregateWindow(every: {}, fn: spread, createEmpty: true) +`; + +export default function analyticsRoute(app: any) { + app.get("/analytics", async (req: any, res: any) => { + const before = new Date().getTime(); + + const timeQuery = req.query.time || "30d"; + const timeInMs = parseTimeToMilliseconds(timeQuery.toString()); + if (timeInMs > 30 * 24 * 60 * 60 * 1000) { + return res.status(400).json({ + error: "Time range too large. Max time range is 30 days.", + }); + } + const shouldUseLongerIntervals = timeInMs > 24 * 60 * 60 * 1000 * 7; // 7 days + + const getActivePlayersHistory = async () => { + const rows = await InfluxQueryAPI.collectRows( + formatString( + getPlayerHistoryQuery, + false, + timeQuery, + shouldUseLongerIntervals ? "1d" : "1h" + ) + ); + let history = rows.map((row: any) => ({ + time: row._time, + value: row._value !== null ? row._value.toFixed(0) : null, + })); + return history.sort( + (a: any, b: any) => + new Date(a.time).getTime() - new Date(b.time).getTime() + ); + }; + + const getScoreCountHistory = async () => { + const rows = await InfluxQueryAPI.collectRows( + formatString( + getScoreCountHistoryQuery, + false, + timeQuery, + shouldUseLongerIntervals ? "1d" : "1h" + ) + ); + let history = rows.map((row: any) => ({ + time: row._time, + value: row._value !== null ? row._value.toFixed(0) : null, + })); + return history.sort( + (a: any, b: any) => + new Date(a.time).getTime() - new Date(b.time).getTime() + ); + }; + + const [activePlayersHistory, scoreCountHistory] = await Promise.all([ + getActivePlayersHistory(), + getScoreCountHistory(), + ]); + + return res.json({ + serverTimeTaken: new Date().getTime() - before + "ms", + activePlayersHistory, + scoreCountHistory, + }); + }); +}