Merge remote-tracking branch 'origin/main'
commit
da92cb9382
|
|
@ -1,3 +1,9 @@
|
||||||
|
## 0.3.0
|
||||||
|
|
||||||
|
feat: clear state when season change
|
||||||
|
|
||||||
|
feat: update `WEB_VIEW_VERSION`
|
||||||
|
|
||||||
## 0.2.9
|
## 0.2.9
|
||||||
|
|
||||||
feat: update `WEB_VIEW_VERSION`
|
feat: update `WEB_VIEW_VERSION`
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@
|
||||||
"fmt": "deno fmt",
|
"fmt": "deno fmt",
|
||||||
"fmt:check": "deno fmt --check",
|
"fmt:check": "deno fmt --check",
|
||||||
"lint": "deno lint",
|
"lint": "deno lint",
|
||||||
"run": "deno run -A"
|
"run": "deno run -A",
|
||||||
|
"gen": "deno run -A ./scripts/update-constant.ts"
|
||||||
},
|
},
|
||||||
"fmt": {
|
"fmt": {
|
||||||
"files": {
|
"files": {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ import { assertEquals } from "../dev_deps.ts";
|
||||||
import { BattleListNode } from "./types.ts";
|
import { BattleListNode } from "./types.ts";
|
||||||
import { base64 } from "../deps.ts";
|
import { base64 } from "../deps.ts";
|
||||||
import { gameId } from "./utils.ts";
|
import { gameId } from "./utils.ts";
|
||||||
|
import { RankState } from "./state.ts";
|
||||||
|
|
||||||
const INIT_STATE = {
|
const INIT_STATE: RankState = {
|
||||||
gameId: await gameId(genId(0)),
|
gameId: await gameId(genId(0)),
|
||||||
rank: "B-",
|
rank: "B-",
|
||||||
rankPoint: 100,
|
rankPoint: 100,
|
||||||
|
|
@ -20,9 +21,9 @@ class TestRankTracker extends RankTracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function genId(id: number): string {
|
function genId(id: number, date = "20220101"): string {
|
||||||
return base64.encode(
|
return base64.encode(
|
||||||
`VsHistoryDetail-asdf:asdf:20220101T${
|
`VsHistoryDetail-asdf:asdf:${date}T${
|
||||||
id.toString().padStart(6, "0")
|
id.toString().padStart(6, "0")
|
||||||
}_------------------------------------`,
|
}_------------------------------------`,
|
||||||
);
|
);
|
||||||
|
|
@ -213,20 +214,7 @@ Deno.test("RankTracker issue #36", async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
assertEquals(await tracker.getRankStateById(genId(0)), undefined);
|
assertEquals(await tracker.getRankStateById(genId(0)), undefined);
|
||||||
assertEquals(await tracker.getRankStateById(genId(1)), {
|
assertEquals(await tracker.getRankStateById(genId(1)), undefined);
|
||||||
before: {
|
|
||||||
gameId: await gameId(genId(0)),
|
|
||||||
rank: "S+19",
|
|
||||||
rankPoint: 3750,
|
|
||||||
timestamp: 1640995200,
|
|
||||||
},
|
|
||||||
after: {
|
|
||||||
gameId: await gameId(genId(1)),
|
|
||||||
rank: "S+19",
|
|
||||||
rankPoint: 3750,
|
|
||||||
timestamp: 1640995201,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
assertEquals(await tracker.getRankStateById(genId(2)), {
|
assertEquals(await tracker.getRankStateById(genId(2)), {
|
||||||
before: {
|
before: {
|
||||||
|
|
@ -491,3 +479,50 @@ Deno.test("RankTracker", async () => {
|
||||||
timestamp: 1640995229,
|
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);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,8 @@ import {
|
||||||
HistoryGroups,
|
HistoryGroups,
|
||||||
RankParam,
|
RankParam,
|
||||||
} from "./types.ts";
|
} from "./types.ts";
|
||||||
import { gameId, nonNullable, parseHistoryDetailId } from "./utils.ts";
|
import { gameId, parseHistoryDetailId } from "./utils.ts";
|
||||||
|
import { getSeason } from "./VersionData.ts";
|
||||||
|
|
||||||
const splusParams = () => {
|
const splusParams = () => {
|
||||||
const out: RankParam[] = [];
|
const out: RankParam[] = [];
|
||||||
|
|
@ -79,9 +80,13 @@ export const RANK_PARAMS: RankParam[] = [{
|
||||||
}, ...splusParams()];
|
}, ...splusParams()];
|
||||||
|
|
||||||
type Delta = {
|
type Delta = {
|
||||||
beforeGameId: string;
|
before: {
|
||||||
|
gameId: string;
|
||||||
|
timestamp: number;
|
||||||
|
};
|
||||||
gameId: string;
|
gameId: string;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
|
rank?: string;
|
||||||
rankAfter?: string;
|
rankAfter?: string;
|
||||||
rankPoint: number;
|
rankPoint: number;
|
||||||
isPromotion: boolean;
|
isPromotion: boolean;
|
||||||
|
|
@ -89,8 +94,24 @@ type Delta = {
|
||||||
isChallengeFirst: boolean;
|
isChallengeFirst: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: auto rank up using rank params and delta.
|
// delta's beforeGameId must be state's gameId
|
||||||
function addRank(state: RankState, delta: Delta): RankState {
|
function addRank(
|
||||||
|
state: RankState | undefined,
|
||||||
|
delta: Delta,
|
||||||
|
): { before: RankState; after: RankState } | undefined {
|
||||||
|
if (!state) {
|
||||||
|
// is rank up, generate state here
|
||||||
|
if (delta.isPromotion && delta.isRankUp) {
|
||||||
|
state = getRankStateByDelta(delta);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.gameId !== delta.before.gameId) {
|
||||||
|
throw new Error("Invalid state");
|
||||||
|
}
|
||||||
|
|
||||||
const { rank, rankPoint } = state;
|
const { rank, rankPoint } = state;
|
||||||
const {
|
const {
|
||||||
gameId,
|
gameId,
|
||||||
|
|
@ -101,6 +122,16 @@ function addRank(state: RankState, delta: Delta): RankState {
|
||||||
isChallengeFirst,
|
isChallengeFirst,
|
||||||
} = delta;
|
} = delta;
|
||||||
|
|
||||||
|
if (state.timestamp) {
|
||||||
|
const oldSeason = getSeason(new Date(state.timestamp * 1000));
|
||||||
|
if (oldSeason) {
|
||||||
|
const newSeason = getSeason(new Date(timestamp * 1000));
|
||||||
|
if (newSeason?.id !== oldSeason.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const rankIndex = RANK_PARAMS.findIndex((r) => r.rank === rank);
|
const rankIndex = RANK_PARAMS.findIndex((r) => r.rank === rank);
|
||||||
|
|
||||||
if (rankIndex === -1) {
|
if (rankIndex === -1) {
|
||||||
|
|
@ -111,20 +142,29 @@ function addRank(state: RankState, delta: Delta): RankState {
|
||||||
|
|
||||||
if (isChallengeFirst) {
|
if (isChallengeFirst) {
|
||||||
return {
|
return {
|
||||||
gameId,
|
before: state,
|
||||||
timestamp,
|
after: {
|
||||||
rank,
|
gameId,
|
||||||
rankPoint: rankPoint - rankParam.charge,
|
timestamp,
|
||||||
|
rank,
|
||||||
|
rankPoint: rankPoint - rankParam.charge,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// S+50 is the highest rank
|
// S+50 is the highest rank
|
||||||
if (rankIndex === RANK_PARAMS.length - 1) {
|
if (rankIndex === RANK_PARAMS.length - 1) {
|
||||||
return {
|
return {
|
||||||
timestamp,
|
before: state,
|
||||||
gameId,
|
after: {
|
||||||
rank,
|
timestamp,
|
||||||
rankPoint: Math.min(rankPoint + delta.rankPoint, rankParam.pointRange[1]),
|
gameId,
|
||||||
|
rank,
|
||||||
|
rankPoint: Math.min(
|
||||||
|
rankPoint + delta.rankPoint,
|
||||||
|
rankParam.pointRange[1],
|
||||||
|
),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,18 +172,24 @@ function addRank(state: RankState, delta: Delta): RankState {
|
||||||
const nextRankParam = RANK_PARAMS[rankIndex + 1];
|
const nextRankParam = RANK_PARAMS[rankIndex + 1];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
gameId,
|
before: state,
|
||||||
timestamp,
|
after: {
|
||||||
rank: nextRankParam.rank,
|
gameId,
|
||||||
rankPoint: nextRankParam.pointRange[0],
|
timestamp,
|
||||||
|
rank: nextRankParam.rank,
|
||||||
|
rankPoint: nextRankParam.pointRange[0],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
gameId,
|
before: state,
|
||||||
timestamp,
|
after: {
|
||||||
rank: rankAfter ?? rank,
|
gameId,
|
||||||
rankPoint: rankPoint + delta.rankPoint,
|
timestamp,
|
||||||
|
rank: rankAfter ?? rank,
|
||||||
|
rankPoint: rankPoint + delta.rankPoint,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,19 +214,39 @@ type FlattenItem = {
|
||||||
detail: BattleListNode;
|
detail: BattleListNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
function generateDeltaList(
|
function beginPoint(
|
||||||
state: RankState,
|
state: RankState | undefined,
|
||||||
flatten: FlattenItem[],
|
flatten: FlattenItem[],
|
||||||
) {
|
): [firstItem: FlattenItem, unProcessed: FlattenItem[]] {
|
||||||
const index = flatten.findIndex((i) => i.gameId === state.gameId);
|
if (state) {
|
||||||
|
const index = flatten.findIndex((i) => i.gameId === state.gameId);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index !== -1) {
|
||||||
return;
|
return [flatten[index], flatten.slice(index)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unProcessed = flatten.slice(index);
|
if (flatten.length === 0) {
|
||||||
|
throw new Error("flatten must not be empty");
|
||||||
|
}
|
||||||
|
return [flatten[0], flatten];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTimestamp(date: Date) {
|
||||||
|
return Math.floor(date.getTime() / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateDeltaList(
|
||||||
|
state: RankState | undefined,
|
||||||
|
flatten: FlattenItem[],
|
||||||
|
) {
|
||||||
|
const [firstItem, unProcessed] = beginPoint(state, flatten);
|
||||||
|
|
||||||
const deltaList: Delta[] = [];
|
const deltaList: Delta[] = [];
|
||||||
let beforeGameId = state.gameId;
|
let before = {
|
||||||
|
gameId: firstItem.gameId,
|
||||||
|
timestamp: getTimestamp(firstItem.time),
|
||||||
|
};
|
||||||
|
|
||||||
for (const i of unProcessed.slice(1)) {
|
for (const i of unProcessed.slice(1)) {
|
||||||
if (!i.detail.bankaraMatch) {
|
if (!i.detail.bankaraMatch) {
|
||||||
|
|
@ -188,21 +254,25 @@ function generateDeltaList(
|
||||||
}
|
}
|
||||||
|
|
||||||
let delta: Delta = {
|
let delta: Delta = {
|
||||||
beforeGameId,
|
before,
|
||||||
gameId: i.gameId,
|
gameId: i.gameId,
|
||||||
timestamp: Math.floor(i.time.getTime() / 1000),
|
timestamp: getTimestamp(i.time),
|
||||||
rankPoint: 0,
|
rankPoint: 0,
|
||||||
isPromotion: false,
|
isPromotion: false,
|
||||||
isRankUp: false,
|
isRankUp: false,
|
||||||
isChallengeFirst: false,
|
isChallengeFirst: false,
|
||||||
};
|
};
|
||||||
beforeGameId = i.gameId;
|
before = {
|
||||||
|
gameId: i.gameId,
|
||||||
|
timestamp: Math.floor(i.time.getTime() / 1000),
|
||||||
|
};
|
||||||
if (i.bankaraMatchChallenge) {
|
if (i.bankaraMatchChallenge) {
|
||||||
// challenge
|
// challenge
|
||||||
if (i.index === 0 && i.bankaraMatchChallenge.state !== "INPROGRESS") {
|
if (i.index === 0 && i.bankaraMatchChallenge.state !== "INPROGRESS") {
|
||||||
// last battle in challenge
|
// last battle in challenge
|
||||||
delta = {
|
delta = {
|
||||||
...delta,
|
...delta,
|
||||||
|
rank: i.detail.udemae,
|
||||||
rankAfter: i.bankaraMatchChallenge.udemaeAfter ?? undefined,
|
rankAfter: i.bankaraMatchChallenge.udemaeAfter ?? undefined,
|
||||||
rankPoint: i.bankaraMatchChallenge.earnedUdemaePoint ?? 0,
|
rankPoint: i.bankaraMatchChallenge.earnedUdemaePoint ?? 0,
|
||||||
isPromotion: i.bankaraMatchChallenge.isPromo ?? false,
|
isPromotion: i.bankaraMatchChallenge.isPromo ?? false,
|
||||||
|
|
@ -229,19 +299,20 @@ function generateDeltaList(
|
||||||
deltaList.push(delta);
|
deltaList.push(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
return deltaList;
|
return {
|
||||||
|
firstItem,
|
||||||
|
deltaList,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRankState(i: FlattenItem): RankState {
|
function getRankStateByDelta(i: Delta): RankState {
|
||||||
const rank = i.detail.udemae;
|
const rank = i.rank;
|
||||||
const nextRank = i.bankaraMatchChallenge?.udemaeAfter;
|
const nextRank = i.rankAfter;
|
||||||
const earnedUdemaePoint = i.bankaraMatchChallenge?.earnedUdemaePoint;
|
const earnedUdemaePoint = i.rankPoint;
|
||||||
if (!nonNullable(earnedUdemaePoint)) {
|
|
||||||
throw new TypeError("earnedUdemaePoint must be defined");
|
|
||||||
}
|
|
||||||
if (!rank || !nextRank) {
|
if (!rank || !nextRank) {
|
||||||
throw new Error("rank and nextRank must be defined");
|
throw new Error("rank and nextRank must be defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
const param = RANK_PARAMS.find((i) => i.rank === rank);
|
const param = RANK_PARAMS.find((i) => i.rank === rank);
|
||||||
const nextParam = RANK_PARAMS.find((i) => i.rank === nextRank);
|
const nextParam = RANK_PARAMS.find((i) => i.rank === nextRank);
|
||||||
|
|
||||||
|
|
@ -253,8 +324,8 @@ function getRankState(i: FlattenItem): RankState {
|
||||||
earnedUdemaePoint;
|
earnedUdemaePoint;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
gameId: i.gameId,
|
gameId: i.before.gameId,
|
||||||
timestamp: Math.floor(i.time.getTime() / 1000),
|
timestamp: i.before.timestamp,
|
||||||
rank,
|
rank,
|
||||||
rankPoint: oldRankPoint,
|
rankPoint: oldRankPoint,
|
||||||
};
|
};
|
||||||
|
|
@ -266,37 +337,18 @@ function getRankState(i: FlattenItem): RankState {
|
||||||
export class RankTracker {
|
export class RankTracker {
|
||||||
// key: privous game id
|
// key: privous game id
|
||||||
protected deltaMap: Map<string, Delta> = new Map();
|
protected deltaMap: Map<string, Delta> = new Map();
|
||||||
|
// key: after game id
|
||||||
|
protected stateMap: Map<string, { before: RankState; after: RankState }> =
|
||||||
|
new Map();
|
||||||
|
|
||||||
constructor(protected state: RankState | undefined) {}
|
constructor(protected state: RankState | undefined) {}
|
||||||
|
|
||||||
async getRankStateById(
|
async getRankStateById(
|
||||||
id: string,
|
id: string,
|
||||||
): Promise<{ before: RankState; after: RankState } | undefined> {
|
): Promise<{ before: RankState; after: RankState } | undefined> {
|
||||||
if (!this.state) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const gid = await gameId(id);
|
const gid = await gameId(id);
|
||||||
|
|
||||||
let cur = this.state;
|
return this.stateMap.get(gid);
|
||||||
let before = cur;
|
|
||||||
|
|
||||||
// there is no delta for first game
|
|
||||||
if (cur.gameId === gid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (cur.gameId !== gid) {
|
|
||||||
const delta = this.deltaMap.get(cur.gameId);
|
|
||||||
if (!delta) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
before = cur;
|
|
||||||
cur = addRank(cur, delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
before,
|
|
||||||
after: cur,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(state: RankState | undefined) {
|
setState(state: RankState | undefined) {
|
||||||
|
|
@ -326,55 +378,22 @@ export class RankTracker {
|
||||||
.map((i) => i.gameId.then((gameId) => ({ ...i, gameId }))),
|
.map((i) => i.gameId.then((gameId) => ({ ...i, gameId }))),
|
||||||
);
|
);
|
||||||
|
|
||||||
const gameIdTime = new Map<string | undefined, Date>(
|
let curState: RankState | undefined = this.state;
|
||||||
flatten.map((i) => [i.gameId, i.time]),
|
|
||||||
);
|
|
||||||
|
|
||||||
let curState: RankState | undefined;
|
const { firstItem, deltaList } = generateDeltaList(curState, flatten);
|
||||||
const oldestPromotion = flatten.find((i) =>
|
|
||||||
i.bankaraMatchChallenge?.isPromo && i.bankaraMatchChallenge.isUdemaeUp
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
// history don't contain current state, so skip update
|
||||||
* There are 4 cases:
|
if (curState && firstItem.gameId !== curState.gameId) {
|
||||||
* 1. state === undefined, oldestPromotion === undefined
|
|
||||||
* 2. state === undefined, oldestPromotion !== undefined
|
|
||||||
* 3. state !== undefined, oldestPromotion === undefined
|
|
||||||
* 4. state !== undefined, oldestPromotion !== undefined
|
|
||||||
*
|
|
||||||
* In case 1, we can't track rank. So we do nothing.
|
|
||||||
* In case 2, 3, we track rank by the non-undefined state.
|
|
||||||
* In case 4, we can track by the elder game.
|
|
||||||
*/
|
|
||||||
const thisStateTime = gameIdTime.get(this.state?.gameId);
|
|
||||||
if (!thisStateTime && !oldestPromotion) {
|
|
||||||
return;
|
|
||||||
} else if (thisStateTime && !oldestPromotion) {
|
|
||||||
curState = this.state;
|
|
||||||
} else if (!thisStateTime && oldestPromotion) {
|
|
||||||
curState = getRankState(oldestPromotion);
|
|
||||||
} else if (thisStateTime && oldestPromotion) {
|
|
||||||
if (thisStateTime <= oldestPromotion.time) {
|
|
||||||
curState = this.state;
|
|
||||||
} else {
|
|
||||||
curState = getRankState(oldestPromotion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!curState) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state = curState;
|
|
||||||
const deltaList = generateDeltaList(curState, flatten);
|
|
||||||
|
|
||||||
if (!deltaList) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const delta of deltaList) {
|
for (const delta of deltaList) {
|
||||||
this.deltaMap.set(delta.beforeGameId, delta);
|
this.deltaMap.set(delta.before.gameId, delta);
|
||||||
curState = addRank(curState, delta);
|
const result = addRank(curState, delta);
|
||||||
|
curState = result?.after;
|
||||||
|
if (result) {
|
||||||
|
this.stateMap.set(result.after.gameId, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return curState;
|
return curState;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { getSeason, SEASONS } from "./VersionData.ts";
|
||||||
|
import { assertEquals } from "../dev_deps.ts";
|
||||||
|
|
||||||
|
Deno.test("Seasons are continuous", () => {
|
||||||
|
let curDate: Date | undefined;
|
||||||
|
for (const season of SEASONS) {
|
||||||
|
if (!curDate) {
|
||||||
|
curDate = season.end;
|
||||||
|
} else {
|
||||||
|
assertEquals(curDate, season.start);
|
||||||
|
curDate = season.end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test("getSeason", () => {
|
||||||
|
const season1 = getSeason(new Date("2022-09-09T00:00:00+00:00"));
|
||||||
|
|
||||||
|
assertEquals(season1?.id, "season202209");
|
||||||
|
|
||||||
|
const season2 = getSeason(new Date("2022-12-09T00:00:00+00:00"));
|
||||||
|
|
||||||
|
assertEquals(season2?.id, "season202212");
|
||||||
|
|
||||||
|
const nonExist = getSeason(new Date("2022-06-09T00:00:00+00:00"));
|
||||||
|
|
||||||
|
assertEquals(nonExist, undefined);
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
export type Season = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
start: Date;
|
||||||
|
end: Date;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SEASONS: Season[] = [
|
||||||
|
{
|
||||||
|
id: "season202209",
|
||||||
|
name: "Drizzle Season 2022",
|
||||||
|
start: new Date("2022-09-01T00:00:00+00:00"),
|
||||||
|
end: new Date("2022-12-01T00:00:00+00:00"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "season202212",
|
||||||
|
name: "Chill Season 2022",
|
||||||
|
start: new Date("2022-12-01T00:00:00+00:00"),
|
||||||
|
end: new Date("2023-03-01T00:00:00+00:00"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const getSeason = (date: Date): Season | undefined => {
|
||||||
|
return SEASONS.find((s) => s.start <= date && date < s.end);
|
||||||
|
};
|
||||||
|
|
@ -2,10 +2,10 @@ import type { StatInkPostBody, VsHistoryDetail } from "./types.ts";
|
||||||
|
|
||||||
export const AGENT_NAME = "splatoon.catgirlin.space / s3si.ts";
|
export const AGENT_NAME = "splatoon.catgirlin.space / s3si.ts";
|
||||||
export const AGENT_VERSION = "1.0.0";
|
export const AGENT_VERSION = "1.0.0";
|
||||||
export const S3SI_VERSION = "0.2.9";
|
export const S3SI_VERSION = "0.3.0";
|
||||||
export const COMBINED_VERSION = `${AGENT_VERSION}/${S3SI_VERSION}`;
|
export const COMBINED_VERSION = `${AGENT_VERSION}/${S3SI_VERSION}`;
|
||||||
export const NSOAPP_VERSION = "2.4.0";
|
export const NSOAPP_VERSION = "2.4.0";
|
||||||
export const WEB_VIEW_VERSION = "2.0.0-7070f95e";
|
export const WEB_VIEW_VERSION = "3.0.0-2857bc50";
|
||||||
export const S3SI_LINK = "https://forgejo.catgirlin.space/catgirl/s3si.ts";
|
export const S3SI_LINK = "https://forgejo.catgirlin.space/catgirl/s3si.ts";
|
||||||
|
|
||||||
export const USERAGENT = `${AGENT_NAME}/(${COMBINED_VERSION}) (${S3SI_LINK})`;
|
export const USERAGENT = `${AGENT_NAME}/(${COMBINED_VERSION}) (${S3SI_LINK})`;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { RankState } from "./state.ts";
|
import { RankState } from "./state.ts";
|
||||||
|
|
||||||
export enum Queries {
|
export enum Queries {
|
||||||
HomeQuery = "dba47124d5ec3090c97ba17db5d2f4b3",
|
HomeQuery = "22e2fa8294168003c21b00c333c35384",
|
||||||
LatestBattleHistoriesQuery = "4f5f26e64bca394b45345a65a2f383bd",
|
LatestBattleHistoriesQuery = "4f5f26e64bca394b45345a65a2f383bd",
|
||||||
RegularBattleHistoriesQuery = "d5b795d09e67ce153e622a184b7e7dfa",
|
RegularBattleHistoriesQuery = "d5b795d09e67ce153e622a184b7e7dfa",
|
||||||
BankaraBattleHistoriesQuery = "de4754588109b77dbcb90fbe44b612ee",
|
BankaraBattleHistoriesQuery = "de4754588109b77dbcb90fbe44b612ee",
|
||||||
|
|
@ -9,7 +9,7 @@ export enum Queries {
|
||||||
PrivateBattleHistoriesQuery = "1d6ed57dc8b801863126ad4f351dfb9a",
|
PrivateBattleHistoriesQuery = "1d6ed57dc8b801863126ad4f351dfb9a",
|
||||||
VsHistoryDetailQuery = "291295ad311b99a6288fc95a5c4cb2d2",
|
VsHistoryDetailQuery = "291295ad311b99a6288fc95a5c4cb2d2",
|
||||||
CoopHistoryQuery = "6ed02537e4a65bbb5e7f4f23092f6154",
|
CoopHistoryQuery = "6ed02537e4a65bbb5e7f4f23092f6154",
|
||||||
CoopHistoryDetailQuery = "3cc5f826a6646b85f3ae45db51bd0707",
|
CoopHistoryDetailQuery = "379f0d9b78b531be53044bcac031b34b",
|
||||||
myOutfitCommonDataFilteringConditionQuery =
|
myOutfitCommonDataFilteringConditionQuery =
|
||||||
"d02ab22c9dccc440076055c8baa0fa7a",
|
"d02ab22c9dccc440076055c8baa0fa7a",
|
||||||
myOutfitCommonDataEquipmentsQuery = "d29cd0c2b5e6bac90dd5b817914832f8",
|
myOutfitCommonDataEquipmentsQuery = "d29cd0c2b5e6bac90dd5b817914832f8",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue