mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-08 14:58:12 +03:00
Merge pull request #150 from zkldi:zkldi/41-Session-Testing
zkldi/41-Session-Testing
This commit is contained in:
@@ -1,10 +1,459 @@
|
||||
import t from "tap";
|
||||
import db from "../../../../external/mongo/db";
|
||||
import { CloseAllConnections } from "../../../../test-utils/close-connections";
|
||||
import ResetDBState from "../../../../test-utils/reset-db-state";
|
||||
import { TestingIIDXSPScore, TestingIIDXSPScorePB } from "../../../../test-utils/test-data";
|
||||
import { CreateScoreLogger } from "../common/import-logger";
|
||||
import { CreateSessions, LoadScoresIntoSessions } from "./sessions";
|
||||
import { PublicUserDocument, ScoreDocument, SessionDocument } from "kamaitachi-common";
|
||||
import deepmerge from "deepmerge";
|
||||
|
||||
t.todo("#CreateSessions", (t) => {
|
||||
const logger = CreateScoreLogger(
|
||||
{ username: "test_zkldi", id: 1 } as PublicUserDocument,
|
||||
"foo",
|
||||
"ir/direct-manual"
|
||||
);
|
||||
|
||||
t.test("#CreateSessions", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
t.beforeEach(() => db.sessions.remove({}));
|
||||
|
||||
t.test("Should compose sessions from one timestamped score provided.", async (t) => {
|
||||
const res = await CreateSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
"iidx",
|
||||
{ SP: [TestingIIDXSPScore] },
|
||||
logger
|
||||
);
|
||||
|
||||
t.match(res, [
|
||||
{
|
||||
sessionID: /^Q[a-f0-9]{40}$/u,
|
||||
type: "Created",
|
||||
},
|
||||
] as any);
|
||||
|
||||
t.equal(res.length, 1);
|
||||
|
||||
const session = await db.sessions.findOne({ userID: 1, game: "iidx", playtype: "SP" });
|
||||
|
||||
const sessionCount = await db.sessions.count({ userID: 1, game: "iidx", playtype: "SP" });
|
||||
|
||||
t.equal(sessionCount, 1);
|
||||
|
||||
t.hasStrict(session, {
|
||||
userID: 1,
|
||||
importType: "ir/direct-manual",
|
||||
// name: "adjective1 adjective2 noun1",
|
||||
sessionID: res[0].sessionID,
|
||||
desc: null,
|
||||
game: "iidx",
|
||||
playtype: "SP",
|
||||
highlight: false,
|
||||
scoreInfo: [
|
||||
{
|
||||
scoreID: "TESTING_SCORE_ID",
|
||||
isNewScore: true,
|
||||
},
|
||||
],
|
||||
// timeInserted: 1622289329729,
|
||||
timeStarted: 1619454485988,
|
||||
timeEnded: 1619454485988,
|
||||
calculatedData: {
|
||||
scorePerf: null,
|
||||
lampPerf: null,
|
||||
perf: null,
|
||||
},
|
||||
} as any);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should not compose sessions from untimestamped scores.", async (t) => {
|
||||
const res = await CreateSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
"iidx",
|
||||
{ SP: [deepmerge(TestingIIDXSPScore, { timeAchieved: null })] },
|
||||
logger
|
||||
);
|
||||
|
||||
t.strictSame(res, []);
|
||||
|
||||
const sessionCount = await db.sessions.count({ userID: 1, game: "iidx", playtype: "SP" });
|
||||
|
||||
t.equal(sessionCount, 0);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should compose sessions for multiple playtypes.", async (t) => {
|
||||
const res = await CreateSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
"iidx",
|
||||
{ DP: [deepmerge(TestingIIDXSPScore, { playtype: "DP" })], SP: [TestingIIDXSPScore] },
|
||||
logger
|
||||
);
|
||||
|
||||
t.equal(res.length, 2);
|
||||
|
||||
const sessionCount = await db.sessions.count({ userID: 1, game: "iidx", playtype: "SP" });
|
||||
|
||||
t.equal(sessionCount, 1);
|
||||
|
||||
const sessionCountDP = await db.sessions.count({ userID: 1, game: "iidx", playtype: "DP" });
|
||||
|
||||
t.equal(sessionCountDP, 1);
|
||||
|
||||
t.end();
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.todo("#LoadScoresIntoSessions", (t) => {
|
||||
// just an arbitrary start point for our sessions as an offset
|
||||
const start = 1619454485988;
|
||||
|
||||
t.test("#LoadScoresIntoSessions", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
t.beforeEach(() => db.sessions.remove({}));
|
||||
|
||||
t.test("Should create sessions from scores.", async (t) => {
|
||||
const res = await LoadScoresIntoSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
[null, start, start + 1000, start + 2000, start + 3000].map((e, i) =>
|
||||
deepmerge(TestingIIDXSPScore, { timeAchieved: e, scoreID: `SCORE_ID_${i}` })
|
||||
) as ScoreDocument[],
|
||||
"iidx",
|
||||
"SP",
|
||||
logger
|
||||
);
|
||||
|
||||
t.match(res, [
|
||||
{
|
||||
sessionID: /^Q[a-f0-9]{40}$/u,
|
||||
type: "Created",
|
||||
},
|
||||
] as any);
|
||||
|
||||
const sessions = await db.sessions.find({ game: "iidx", playtype: "SP", userID: 1 });
|
||||
|
||||
t.equal(sessions.length, 1);
|
||||
|
||||
t.strictSame(sessions[0].scoreInfo, [
|
||||
{
|
||||
scoreID: "SCORE_ID_1",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_2",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_3",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_4",
|
||||
isNewScore: true,
|
||||
},
|
||||
]);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should sort scores before creating sessions.", async (t) => {
|
||||
const res = await LoadScoresIntoSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
[
|
||||
null,
|
||||
start,
|
||||
start - 4000,
|
||||
start + 2000,
|
||||
start - 3000,
|
||||
null,
|
||||
start + 1000,
|
||||
].map((e, i) =>
|
||||
deepmerge(TestingIIDXSPScore, { timeAchieved: e, scoreID: `SCORE_ID_${i}` })
|
||||
) as ScoreDocument[],
|
||||
"iidx",
|
||||
"SP",
|
||||
logger
|
||||
);
|
||||
|
||||
t.match(res, [
|
||||
{
|
||||
sessionID: /^Q[a-f0-9]{40}$/u,
|
||||
type: "Created",
|
||||
},
|
||||
] as any);
|
||||
|
||||
const sessions = await db.sessions.find({ game: "iidx", playtype: "SP", userID: 1 });
|
||||
|
||||
t.equal(sessions.length, 1);
|
||||
|
||||
t.strictSame(sessions[0].scoreInfo, [
|
||||
{
|
||||
scoreID: "SCORE_ID_2",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_4",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_1",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_6",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_3",
|
||||
isNewScore: true,
|
||||
},
|
||||
]);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
const TWO_HOURS = 1000 * 60 * 60 * 2;
|
||||
|
||||
t.test("Should create multiple sessions if scores are far apart.", async (t) => {
|
||||
const res = await LoadScoresIntoSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
[
|
||||
null,
|
||||
start,
|
||||
start + 1000,
|
||||
start + 2000,
|
||||
start + TWO_HOURS + 4000,
|
||||
start + TWO_HOURS + 5000,
|
||||
start + TWO_HOURS + 6000,
|
||||
].map((e, i) =>
|
||||
deepmerge(TestingIIDXSPScore, { timeAchieved: e, scoreID: `SCORE_ID_${i}` })
|
||||
) as ScoreDocument[],
|
||||
"iidx",
|
||||
"SP",
|
||||
logger
|
||||
);
|
||||
|
||||
t.match(res, [
|
||||
{
|
||||
sessionID: /^Q[a-f0-9]{40}$/u,
|
||||
type: "Created",
|
||||
},
|
||||
{
|
||||
sessionID: /^Q[a-f0-9]{40}$/u,
|
||||
type: "Created",
|
||||
},
|
||||
] as any);
|
||||
|
||||
const sessions = await db.sessions.find({ game: "iidx", playtype: "SP", userID: 1 });
|
||||
|
||||
t.equal(sessions.length, 2);
|
||||
|
||||
t.strictSame(sessions[0].scoreInfo, [
|
||||
{
|
||||
scoreID: "SCORE_ID_1",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_2",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_3",
|
||||
isNewScore: true,
|
||||
},
|
||||
]);
|
||||
t.strictSame(sessions[1].scoreInfo, [
|
||||
{
|
||||
scoreID: "SCORE_ID_4",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_5",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_6",
|
||||
isNewScore: true,
|
||||
},
|
||||
]);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should append to existing sessions.", async (t) => {
|
||||
await db.sessions.insert({
|
||||
sessionID: "EXAMPLE_SESSION_ID",
|
||||
userID: 1,
|
||||
game: "iidx",
|
||||
playtype: "SP",
|
||||
importType: "ir/direct-manual",
|
||||
timeStarted: start,
|
||||
timeEnded: start,
|
||||
scoreInfo: [
|
||||
{
|
||||
scoreID: "EXAMPLE_SCORE_ID",
|
||||
isNewScore: true,
|
||||
},
|
||||
],
|
||||
} as SessionDocument);
|
||||
|
||||
const res = await LoadScoresIntoSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
[null, start, start + 1000, start + 2000].map((e, i) =>
|
||||
deepmerge(TestingIIDXSPScore, { timeAchieved: e, scoreID: `SCORE_ID_${i}` })
|
||||
) as ScoreDocument[],
|
||||
"iidx",
|
||||
"SP",
|
||||
logger
|
||||
);
|
||||
|
||||
t.strictSame(res, [
|
||||
{
|
||||
sessionID: "EXAMPLE_SESSION_ID",
|
||||
type: "Appended",
|
||||
},
|
||||
] as any);
|
||||
|
||||
const sessions = await db.sessions.find({ game: "iidx", playtype: "SP", userID: 1 });
|
||||
|
||||
t.equal(sessions.length, 1);
|
||||
|
||||
t.strictSame(sessions[0].scoreInfo, [
|
||||
{
|
||||
scoreID: "EXAMPLE_SCORE_ID",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_1",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_2",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_3",
|
||||
isNewScore: true,
|
||||
},
|
||||
]);
|
||||
|
||||
t.equal(sessions[0].timeEnded, start + 2000);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should change the timeStarted of existing sessions if prepending.", async (t) => {
|
||||
await db.sessions.insert({
|
||||
sessionID: "EXAMPLE_SESSION_ID",
|
||||
userID: 1,
|
||||
game: "iidx",
|
||||
playtype: "SP",
|
||||
importType: "ir/direct-manual",
|
||||
timeStarted: start,
|
||||
timeEnded: start,
|
||||
scoreInfo: [
|
||||
{
|
||||
scoreID: "EXAMPLE_SCORE_ID",
|
||||
isNewScore: true,
|
||||
},
|
||||
],
|
||||
} as SessionDocument);
|
||||
|
||||
const res = await LoadScoresIntoSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
[null, start, start - 1000, start - 2000].map((e, i) =>
|
||||
deepmerge(TestingIIDXSPScore, { timeAchieved: e, scoreID: `SCORE_ID_${i}` })
|
||||
) as ScoreDocument[],
|
||||
"iidx",
|
||||
"SP",
|
||||
logger
|
||||
);
|
||||
|
||||
t.strictSame(res, [
|
||||
{
|
||||
sessionID: "EXAMPLE_SESSION_ID",
|
||||
type: "Appended",
|
||||
},
|
||||
] as any);
|
||||
|
||||
const sessions = await db.sessions.find({ game: "iidx", playtype: "SP", userID: 1 });
|
||||
|
||||
t.equal(sessions.length, 1);
|
||||
|
||||
t.strictSame(sessions[0].scoreInfo, [
|
||||
{
|
||||
scoreID: "EXAMPLE_SCORE_ID",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_3",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_2",
|
||||
isNewScore: true,
|
||||
},
|
||||
{
|
||||
scoreID: "SCORE_ID_1",
|
||||
isNewScore: true,
|
||||
},
|
||||
]);
|
||||
|
||||
t.equal(sessions[0].timeStarted, start - 2000);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should calculate pbDifferences if a scorePB exists.", async (t) => {
|
||||
await db["score-pbs"].insert(TestingIIDXSPScorePB);
|
||||
|
||||
const res = await LoadScoresIntoSessions(
|
||||
1,
|
||||
"ir/direct-manual",
|
||||
[TestingIIDXSPScore],
|
||||
"iidx",
|
||||
"SP",
|
||||
logger
|
||||
);
|
||||
|
||||
t.match(res, [
|
||||
{
|
||||
sessionID: /^Q[a-f0-9]{40}$/u,
|
||||
type: "Created",
|
||||
},
|
||||
] as any);
|
||||
|
||||
const sessions = await db.sessions.find({ game: "iidx", playtype: "SP", userID: 1 });
|
||||
|
||||
t.equal(sessions.length, 1);
|
||||
|
||||
t.strictSame(sessions[0].scoreInfo, [
|
||||
{
|
||||
scoreID: "TESTING_SCORE_ID",
|
||||
isNewScore: false,
|
||||
gradeDelta: 4,
|
||||
lampDelta: -2,
|
||||
percentDelta: -44.08396946564885,
|
||||
scoreDelta: -693,
|
||||
},
|
||||
]);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.teardown(CloseAllConnections);
|
||||
|
||||
@@ -50,6 +50,10 @@ export async function CreateSessions(
|
||||
return allSessionInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares a score and the previous PB the user had and returns the difference
|
||||
* as a SessionScoreInfo object.
|
||||
*/
|
||||
function ProcessScoreIntoSessionScoreInfo(
|
||||
score: ScoreDocument,
|
||||
previousPB: PBScoreDocument | undefined
|
||||
@@ -176,10 +180,9 @@ export async function LoadScoresIntoSessions(
|
||||
lastTimestamp = score.timeAchieved!;
|
||||
}
|
||||
|
||||
// I think this check is redundant?
|
||||
if (curGroup.length !== 0) {
|
||||
sessionScoreGroups.push(curGroup);
|
||||
}
|
||||
// There's no state here where curGroup is empty,
|
||||
// so push the group (which is guaranteed to have atleast one score)
|
||||
sessionScoreGroups.push(curGroup);
|
||||
|
||||
logger.verbose(`Created ${sessionScoreGroups.length} groups from timestamped scores.`);
|
||||
|
||||
@@ -212,11 +215,12 @@ export async function LoadScoresIntoSessions(
|
||||
|
||||
// Find any sessions with +/-2hrs of this group. This is rather exhaustive, and could result in some issues
|
||||
// if this query returns more than one session. We should account for that by smushing sessions together.
|
||||
// As of now, we dont currently do it. @TODO.
|
||||
// As of now, we dont currently do it. @TODO #148.
|
||||
const nearbySession = await db.sessions.findOne({
|
||||
userID,
|
||||
game,
|
||||
playtype,
|
||||
importType,
|
||||
$or: [
|
||||
{ timeStarted: { $gte: startOfGroup - TWO_HOURS, $lt: endOfGroup + TWO_HOURS } },
|
||||
{ timeEnded: { $gte: startOfGroup - TWO_HOURS, $lt: endOfGroup + TWO_HOURS } },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"service": "e-amusement",
|
||||
"service": "foo (DIRECT-MANUAL)",
|
||||
"game": "iidx",
|
||||
"playtype": "SP",
|
||||
"difficulty": "ANOTHER",
|
||||
@@ -24,7 +24,7 @@
|
||||
"lampRating": 5,
|
||||
"gameSpecific": {}
|
||||
},
|
||||
"timeAchieved": null,
|
||||
"timeAchieved": 1619454485988,
|
||||
"songID": 1,
|
||||
"chartID": "c2311194e3897ddb5745b1760d2c0141f933e683",
|
||||
"highlight": false,
|
||||
@@ -32,5 +32,5 @@
|
||||
"comment": null,
|
||||
"timeAdded": 1,
|
||||
"scoreID": "TESTING_SCORE_ID",
|
||||
"importType": "iidx:eamusement-csv"
|
||||
"importType": "ir/direct-manual"
|
||||
}
|
||||
Reference in New Issue
Block a user