Skip to content

Commit 37b2198

Browse files
committed
fix(taruchi): skip unrevealed detail records
1 parent ff29001 commit 37b2198

3 files changed

Lines changed: 41 additions & 7 deletions

File tree

packages/store-indexer/src/leaderboard/buildTaruchiDetails.test.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
type TaruchiStatusRow,
1111
} from "./buildTaruchiDetails";
1212

13-
const MASK_16 = 0xffffn;
1413
const i16 = (n: number): bigint => BigInt(n & 0xffff);
1514
const packStats = (health: number, power: number, harmony: number, violence: number): bigint =>
1615
i16(health) | (i16(power) << 16n) | (i16(harmony) << 32n) | (i16(violence) << 48n);
@@ -197,11 +196,6 @@ describe("buildTaruchiDetails", () => {
197196
expect(d.ascended).toBe(false);
198197
});
199198

200-
// Guard the int16 mask constant the helpers rely on.
201-
it("uses a 16-bit mask", () => {
202-
expect(MASK_16).toBe(0xffffn);
203-
});
204-
205199
it("splits eight-player festival results into the collapsed tier bucket", () => {
206200
const festivalCores = Array.from({ length: 8 }, (_, i) => ({
207201
id: BigInt(1000 + i),
@@ -237,4 +231,35 @@ describe("buildTaruchiDetails", () => {
237231
champion: { wins: 0, losses: 0 },
238232
});
239233
});
234+
235+
it("does not accumulate bracket records for unrevealed tarus", () => {
236+
const unrevealedCore = { id: 400n, owner: "0xDDD", index: 4 };
237+
const out = buildTaruchiDetails({
238+
tourneys: [],
239+
duels: [{ id: 123n, status: 2, bracket: 1, playerAIndex: 4, playerBIndex: 99 }],
240+
results: [{ id: 123n, placements: packU32([4, 99]) }],
241+
cores: [unrevealedCore],
242+
statuses: [status({ id: 400n, state: 0 })],
243+
names: [],
244+
byTaruchi: new Map(),
245+
spriteFor: (core) => `sprite/${core.index}`,
246+
decodeName: (s) => s,
247+
});
248+
249+
expect(out.get("400")!.record).toEqual({
250+
wins: 0,
251+
losses: 0,
252+
tournaments: 0,
253+
bestPlacement: 8,
254+
winrate: 0,
255+
qualified: false,
256+
onyxWon: 0,
257+
onyxSpent: 0,
258+
});
259+
expect(out.get("400")!.bracketRecord).toEqual({
260+
rookie: { wins: 0, losses: 0 },
261+
veteran: { wins: 0, losses: 0 },
262+
champion: { wins: 0, losses: 0 },
263+
});
264+
});
240265
});

packages/store-indexer/src/leaderboard/buildTaruchiDetails.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export interface BuildTaruchiDetailsInput {
119119
decodeName: (name: string) => string;
120120
}
121121

122+
const TARUCHI_STATE_UNREVEALED = 0;
122123
const TARUCHI_STATE_ASCENDED = 4;
123124
const NEVER_PLACED = 8;
124125
const MASK_16 = 0xffffn;
@@ -177,8 +178,14 @@ export function buildTaruchiDetails(input: BuildTaruchiDetailsInput): Map<string
177178
const { tourneys, duels, results, cores, statuses, names, byTaruchi, spriteFor, decodeName } = input;
178179

179180
const statusById = new Map(statuses.map((s) => [String(s.id), s]));
181+
const coreByIndex = new Map(cores.map((c) => [c.index, c]));
180182
const nameById = new Map(names.map((n) => [String(n.id), n.name]));
181183
const resultById = new Map(results.map((r) => [String(r.id), r.placements]));
184+
const shouldAccumulateIndex = (idx: number): boolean => {
185+
const core = coreByIndex.get(idx);
186+
if (!core) return false;
187+
return statusById.get(String(core.id))?.state !== TARUCHI_STATE_UNREVEALED;
188+
};
182189

183190
// Per-tier W/L, keyed by taruchi index, using the SAME placement → won/lost
184191
// math as buildAggregate so the tiers sum to the overall record.
@@ -206,6 +213,7 @@ export function buildTaruchiDetails(input: BuildTaruchiDetailsInput): Map<string
206213
for (const idx of players) {
207214
if (seen.has(idx)) continue;
208215
seen.add(idx);
216+
if (!shouldAccumulateIndex(idx)) continue;
209217
const pos = posByIdx.get(idx);
210218
if (pos === undefined) continue;
211219
const placement = positionToPlacement(pos, placements.length);
@@ -227,6 +235,7 @@ export function buildTaruchiDetails(input: BuildTaruchiDetailsInput): Map<string
227235
const p0 = placements[0];
228236
const p1 = placements[1];
229237
for (const idx of [d.playerAIndex, d.playerBIndex]) {
238+
if (!shouldAccumulateIndex(idx)) continue;
230239
const pos = p0 === idx ? 0 : p1 === idx ? 1 : -1;
231240
if (pos === -1) continue;
232241
const placement = positionToPlacement(pos, placements.length);

packages/store-indexer/src/postgres/aggregateCache.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ export function createLeaderboardCache(
408408
getStats: (wallet) => state.aggregate.byWallet.get(wallet.toLowerCase()) ?? null,
409409
getRoster: (wallet) => state.rosterByOwner.get(wallet.toLowerCase()) ?? [],
410410
getBattles: (wallet) => state.matchesByOwner.get(wallet.toLowerCase()) ?? [],
411-
getTaruchi: (id) => state.detailById.get(String(id)) ?? null,
411+
getTaruchi: (id) => state.detailById.get(id) ?? null,
412412
computedAt: () => state.computedAt,
413413
indexedBlock: () => state.indexedBlock,
414414
rebuildNow,

0 commit comments

Comments
 (0)