s3si.ts/src/RankTracker.test.ts

529 lines
11 KiB
TypeScript

import { RankTracker } from "./RankTracker.ts";
import { assertEquals } from "../dev_deps.ts";
import { BattleListNode } from "./types.ts";
import { base64 } from "../deps.ts";
import { gameId } from "./utils.ts";
import { RankState } from "./state.ts";
const INIT_STATE: RankState = {
gameId: await gameId(genId(0)),
rank: "B-",
rankPoint: 100,
};
class TestRankTracker extends RankTracker {
testGet() {
const { state, deltaMap } = this;
return {
state,
deltaMap,
};
}
}
function genId(id: number, date = "20220101"): string {
return base64.encode(
`VsHistoryDetail-asdf:asdf:${date}T${
id.toString().padStart(6, "0")
}_------------------------------------`,
);
}
function genOpenWins(
{ startId, count, udemae }: {
startId: number;
count: number;
udemae: string;
},
) {
const result: BattleListNode[] = [];
let id = startId;
for (let i = 0; i < count; i++) {
result.push({
id: genId(id),
udemae,
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: 8,
},
});
id += 1;
}
return result;
}
Deno.test("RankTracker don't promo after failed challenge", async () => {
const tracker = new TestRankTracker(undefined);
assertEquals(tracker.testGet(), {
state: undefined,
deltaMap: new Map(),
});
const finalState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: {
winCount: 0,
loseCount: 3,
maxWinCount: 3,
maxLoseCount: 3,
state: "FAILED",
isPromo: true,
isUdemaeUp: false,
udemaeAfter: "B+",
earnedUdemaePoint: null,
},
historyDetails: {
nodes: [{
id: genId(1),
udemae: "B+",
judgement: "LOSE",
bankaraMatch: {
earnedUdemaePoint: null,
},
}, {
id: genId(0),
udemae: "B+",
judgement: "LOSE",
bankaraMatch: {
earnedUdemaePoint: null,
},
}],
},
}]);
assertEquals(finalState, undefined);
});
Deno.test("RankTracker autotrack after promotion", async () => {
const tracker = new TestRankTracker(undefined);
assertEquals(tracker.testGet(), {
state: undefined,
deltaMap: new Map(),
});
const finalState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: {
winCount: 3,
loseCount: 0,
maxWinCount: 3,
maxLoseCount: 3,
state: "SUCCEEDED",
isPromo: true,
isUdemaeUp: true,
udemaeAfter: "A-",
earnedUdemaePoint: -233,
},
historyDetails: {
nodes: [{
id: genId(1),
udemae: "B+",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}, {
id: genId(0),
udemae: "B+",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}],
},
}]);
const gameId1 = await gameId(genId(1));
assertEquals(finalState, {
gameId: gameId1,
rank: "A-",
rankPoint: 200,
timestamp: 1640995201,
});
assertEquals(await tracker.getRankStateById(genId(1)), {
before: {
gameId: await gameId(genId(0)),
rank: "B+",
rankPoint: 433,
timestamp: 1640995200,
},
after: {
gameId: gameId1,
rank: "A-",
rankPoint: 200,
timestamp: 1640995201,
},
});
});
Deno.test("RankTracker issue #36", async () => {
const tracker = new TestRankTracker(undefined);
assertEquals(tracker.testGet(), {
state: undefined,
deltaMap: new Map(),
});
const finalState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: {
winCount: 3,
loseCount: 0,
maxWinCount: 3,
maxLoseCount: 3,
state: "SUCCEEDED",
isPromo: true,
isUdemaeUp: true,
udemaeAfter: "S+20",
earnedUdemaePoint: -3450,
},
historyDetails: {
nodes: [{
id: genId(2),
udemae: "S+19",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}, {
id: genId(1),
udemae: "S+19",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}, {
id: genId(0),
udemae: "S+19",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}],
},
}]);
const gameId2 = await gameId(genId(2));
assertEquals(finalState, {
gameId: gameId2,
rank: "S+20",
rankPoint: 300,
timestamp: 1640995202,
});
assertEquals(await tracker.getRankStateById(genId(0)), undefined);
assertEquals(await tracker.getRankStateById(genId(1)), undefined);
assertEquals(await tracker.getRankStateById(genId(2)), {
before: {
gameId: await gameId(genId(1)),
rank: "S+19",
rankPoint: 3750,
timestamp: 1640995201,
},
after: {
gameId: gameId2,
rank: "S+20",
rankPoint: 300,
timestamp: 1640995202,
},
});
});
Deno.test("RankTracker tracks promotion, ignoring INPROGRESS", async () => {
const INIT_STATE = {
gameId: await gameId(genId(0)),
rank: "B+",
rankPoint: 850,
timestamp: 1640995201,
};
const tracker = new TestRankTracker(INIT_STATE);
assertEquals(tracker.testGet(), {
state: INIT_STATE,
deltaMap: new Map(),
});
const finalState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: {
winCount: 2,
loseCount: 0,
maxWinCount: 3,
maxLoseCount: 3,
state: "INPROGRESS",
isPromo: true,
isUdemaeUp: true,
udemaeAfter: "A-",
earnedUdemaePoint: null,
},
historyDetails: {
nodes: [{
id: genId(1),
udemae: "B+",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}, {
id: genId(0),
udemae: "B+",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}],
},
}]);
assertEquals(finalState, {
gameId: await gameId(genId(1)),
rank: "B+",
rankPoint: 850,
timestamp: 1640995201,
});
});
Deno.test("RankTracker tracks promotion", async () => {
const INIT_STATE = {
gameId: await gameId(genId(0)),
rank: "B+",
rankPoint: 850,
};
const tracker = new TestRankTracker(INIT_STATE);
assertEquals(tracker.testGet(), {
state: INIT_STATE,
deltaMap: new Map(),
});
const finalState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: {
winCount: 3,
loseCount: 0,
maxWinCount: 3,
maxLoseCount: 3,
state: "SUCCEEDED",
isPromo: true,
isUdemaeUp: true,
udemaeAfter: "A-",
earnedUdemaePoint: null,
},
historyDetails: {
nodes: [{
id: genId(2),
udemae: "B+",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}, {
id: genId(1),
udemae: "B+",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}, {
id: genId(0),
udemae: "B+",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
}],
},
}]);
assertEquals(finalState, {
gameId: await gameId(genId(2)),
rank: "A-",
rankPoint: 200,
timestamp: 1640995202,
});
});
Deno.test("RankTracker tracks challenge charge", async () => {
const tracker = new TestRankTracker(INIT_STATE);
assertEquals(tracker.testGet(), {
state: INIT_STATE,
deltaMap: new Map(),
});
const finalState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: {
winCount: 1,
loseCount: 0,
maxWinCount: 5,
maxLoseCount: 3,
isPromo: false,
isUdemaeUp: false,
udemaeAfter: null,
earnedUdemaePoint: null,
state: "INPROGRESS",
},
historyDetails: {
nodes: [
{
id: genId(2),
udemae: "B-",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: null,
},
},
],
},
}, {
xMatchMeasurement: null,
bankaraMatchChallenge: null,
historyDetails: {
nodes: genOpenWins({
startId: 0,
count: 1,
udemae: "B-",
}),
},
}]);
assertEquals(tracker.testGet().state, INIT_STATE);
assertEquals(finalState, {
gameId: await gameId(genId(2)),
rank: "B-",
rankPoint: 45,
timestamp: 1640995202,
});
});
Deno.test("RankTracker", async () => {
const tracker = new TestRankTracker(INIT_STATE);
assertEquals(tracker.testGet(), {
state: INIT_STATE,
deltaMap: new Map(),
});
const finalState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: null,
historyDetails: {
nodes: [...genOpenWins({
startId: 0,
count: 19,
udemae: "B-",
})].reverse(),
},
}]);
assertEquals(tracker.testGet().state, INIT_STATE);
assertEquals(finalState, {
gameId: await gameId(genId(18)),
rank: "B-",
rankPoint: 244,
timestamp: 1640995218,
});
assertEquals((await tracker.getRankStateById(genId(1)))?.after, {
gameId: await gameId(genId(1)),
rank: "B-",
rankPoint: 108,
timestamp: 1640995201,
});
assertEquals((await tracker.getRankStateById(genId(17)))?.after, {
gameId: await gameId(genId(17)),
rank: "B-",
rankPoint: 236,
timestamp: 1640995217,
});
tracker.setState(finalState);
assertEquals(tracker.testGet().state, finalState);
// history goes too far
const finalState2 = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: null,
historyDetails: {
nodes: [...genOpenWins({
startId: 30,
count: 1,
udemae: "B-",
})].reverse(),
},
}]);
assertEquals(finalState2, undefined);
await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: null,
historyDetails: {
nodes: [...genOpenWins({
startId: 0,
count: 30,
udemae: "B-",
})].reverse(),
},
}]);
assertEquals((await tracker.getRankStateById(genId(29)))?.after, {
gameId: await gameId(genId(29)),
rank: "B-",
rankPoint: 332,
timestamp: 1640995229,
});
});
Deno.test("RankTracker clears state when season changes", async () => {
const firstDay = new Date("2022-09-09T00:00:00+00:00").getTime() / 1000;
const firstSeason = {
...INIT_STATE,
timestamp: firstDay,
};
const tracker = new TestRankTracker(firstSeason);
assertEquals(tracker.testGet(), {
state: firstSeason,
deltaMap: new Map(),
});
const afterState = await tracker.updateState([{
xMatchMeasurement: null,
bankaraMatchChallenge: {
winCount: 3,
loseCount: 0,
maxWinCount: 3,
maxLoseCount: 3,
state: "SUCCEEDED",
isPromo: true,
isUdemaeUp: true,
udemaeAfter: "B-",
earnedUdemaePoint: 1,
},
historyDetails: {
nodes: [{
id: genId(1, "20221209"),
udemae: "B-",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: 8,
},
}, {
id: genId(0),
udemae: "B-",
judgement: "WIN",
bankaraMatch: {
earnedUdemaePoint: 8,
},
}],
},
}]);
assertEquals(afterState, undefined);
});