change how score stats are stored - much cleaner
All checks were successful
deploy / deploy (push) Successful in 29s

This commit is contained in:
Lee 2023-10-30 20:14:50 +00:00
parent d023efe9e6
commit 410dc1c52c
3 changed files with 44 additions and 146 deletions

@ -4,8 +4,6 @@ const { Schema } = mongoose;
const leaderboardSchema = new Schema({ const leaderboardSchema = new Schema({
_id: String, _id: String,
totalPlays: Number, totalPlays: Number,
countries: JSON,
headsets: JSON,
}); });
export const LeaderboardSchema = export const LeaderboardSchema =

@ -1,21 +0,0 @@
import mongoose from "mongoose";
const { Schema } = mongoose;
const scoreSchema = new Schema({
_id: String,
player: {
id: String,
},
acc: Number,
pp: Number,
stars: Number,
mistakes: {
badCuts: Number,
missed: Number,
},
rank: Number,
maxCombo: Number,
});
export const Score =
mongoose.models.Score || mongoose.model("Score", scoreSchema);

@ -4,7 +4,6 @@ import { w3cwebsocket as WebsocketClient } from "websocket";
import { InfluxWriteAPI } from ".."; import { InfluxWriteAPI } from "..";
import { connectMongo } from "../db/mongo"; import { connectMongo } from "../db/mongo";
import { LeaderboardSchema } from "../db/schemas/leaderboard"; import { LeaderboardSchema } from "../db/schemas/leaderboard";
import { Score } from "../db/schemas/score";
import { Headsets } from "../headsets"; import { Headsets } from "../headsets";
import { normalizedRegionName } from "../utils/regionUtils"; import { normalizedRegionName } from "../utils/regionUtils";
@ -66,34 +65,12 @@ async function connectWebsocket() {
baseScore, baseScore,
missedNotes, missedNotes,
badCuts, badCuts,
rank,
maxCombo,
leaderboardPlayerInfo: player, leaderboardPlayerInfo: player,
pp, pp,
} = score; } = score;
const { maxScore, stars, id: leaderboardId } = leaderboard; const { maxScore, stars, id: leaderboardId } = leaderboard;
await Score.deleteOne({ _id: id }); // Delete the score if it already exists
const data: any = {
_id: id,
player: {
id: player.id,
},
mistakes: {
badCuts: badCuts,
missed: missedNotes,
},
rank: score.rank,
maxCombo: score.maxCombo,
leaderboardId: leaderboardId,
};
if (maxScore) {
data.acc = ((baseScore / maxScore) * 100).toFixed(2);
}
if (pp && stars > 0) {
data.pp = pp;
data.stars = stars;
}
Score.create(data); // Create the score
const hmdName = const hmdName =
Headsets.find((h) => h.id.includes(hmd))?.name || "Unknown"; Headsets.find((h) => h.id.includes(hmd))?.name || "Unknown";
@ -113,114 +90,58 @@ async function connectWebsocket() {
} }
).exec(); ).exec();
// Write the metrics data to influx const scorePoint = new Point("scoresaber")
.tag("type", "score")
.intField("id", id)
.timestamp(new Date());
if (baseScore && maxScore) {
scorePoint.floatField("acc", (baseScore / maxScore) * 100);
}
if (stars) {
scorePoint.floatField("stars", stars);
}
if (pp) {
scorePoint.floatField("pp", pp);
}
if (missedNotes) {
scorePoint.intField("missed_notes", missedNotes);
}
if (badCuts) {
scorePoint.intField("bad_cuts", badCuts);
}
if (rank) {
scorePoint.intField("rank", rank);
}
if (leaderboardId) {
scorePoint.intField("leaderboard_id", leaderboardId);
}
if (hmdName) {
scorePoint.stringField("hmd", hmdName);
}
if (countryId) {
scorePoint.stringField("country", countryId);
}
if (maxCombo) {
scorePoint.intField("max_combo", maxCombo);
}
scorePoint.intField("player_id", player.id);
// Write the data to influx
InfluxWriteAPI.writePoint(scorePoint);
InfluxWriteAPI.writePoint( InfluxWriteAPI.writePoint(
new Point("scoresaber") new Point("scoresaber")
.tag("type", "score_count") .tag("type", "score_count")
.intField("value", totalScores) .intField("value", totalScores)
.timestamp(new Date()) .timestamp(new Date())
); );
InfluxWriteAPI.writePoint(
new Point("scoresaber") InfluxWriteAPI.flush(); // temp
.tag("type", "headsets")
.tag("hmd", hmdName)
.intField("value", totalHeadsets[hmdName])
.timestamp(new Date())
);
InfluxWriteAPI.writePoint(
new Point("scoresaber")
.tag("type", "countries")
.tag("country", countryId)
.intField("value", totalCountries[countryId])
.timestamp(new Date())
);
} }
}; };
} }
async function updateAverages() {
const before = new Date().getTime();
Score.find({}).then((scores) => {
// create an average for all data for all scores
const average = {
acc: 0,
pp: 0,
stars: 0,
mistakes: {
badCuts: 0,
missed: 0,
},
rank: 0,
maxCombo: 0,
};
const rankedScores = scores.filter((score) => score.pp);
const scoresWithAccuracy = scores.filter((score) => score.acc);
scores.forEach((score) => {
if (score.acc) {
average.acc += score.acc;
}
if (score.pp) {
average.pp += score.pp;
}
if (score.stars) {
average.stars += score.stars;
}
if (score.mistakes) {
average.mistakes.badCuts += score.mistakes.badCuts;
average.mistakes.missed += score.mistakes.missed;
}
if (score.rank) {
average.rank += score.rank;
}
if (score.maxCombo) {
average.maxCombo += score.maxCombo;
}
});
average.acc /= scoresWithAccuracy.length;
average.pp /= rankedScores.length;
average.stars /= rankedScores.length;
average.mistakes.badCuts /= scores.length;
average.mistakes.missed /= scores.length;
average.rank /= scores.length;
average.maxCombo /= scores.length;
// create the point and write it to influx
const point = new Point("scoresaber")
.tag("type", "average")
.timestamp(new Date());
if (average.acc) {
point.floatField("acc", average.acc);
}
if (average.pp) {
point.floatField("pp", average.pp);
}
if (average.stars) {
point.floatField("stars", average.stars);
}
if (average.mistakes) {
point.intField(
"badCuts",
isNaN(average.mistakes.badCuts) ? 0 : average.mistakes.badCuts
);
point.intField(
"missed",
isNaN(average.mistakes.missed) ? 0 : average.mistakes.missed
);
}
if (average.rank) {
point.intField("rank", average.rank);
}
if (average.maxCombo) {
point.intField("maxCombo", average.maxCombo);
}
InfluxWriteAPI.writePoint(point);
console.log(`Updated averages in ${new Date().getTime() - before}ms`);
});
}
update(); update();
updateAverages();
connectWebsocket(); connectWebsocket();
setInterval(update, 60_000); // 1 minute setInterval(update, 60_000); // 1 minute
setInterval(updateAverages, 60_000); // 5 minutes