Record human/nation/bot conquests (#2949)

## Description:

Conquests are currently mixing all player types.

This is not ideal as people wonders why a 50 player game can lead to
hundred of kills.
Having separate records can also help with achievements and better
balancing.

This PR splits the conquests record into 3 categories: human, nations
and bots.

It is linked to this infra PR:
https://github.com/openfrontio/infra/pull/246

<img width="895" height="497" alt="image"
src="https://github.com/user-attachments/assets/66e49100-8114-4406-84ab-d9627355956d"
/>

While the recorded data make a distinction between bots/nations, it's
only displayed here as a single "bot" category.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

IngloriousTom
This commit is contained in:
DevelopingTom
2026-01-19 05:51:12 +01:00
committed by GitHub
parent d92008f96b
commit f367ea1940
10 changed files with 83 additions and 39 deletions
+8 -8
View File
@@ -56,7 +56,7 @@ describe("Ranking class", () => {
cosmetics: { flag: "USA" },
stats: {
units: { port: [2n, 0n, 0n, 2n] },
conquests: 5n,
conquests: [5n],
gold: [0n, 100n, 20n, 0n, 15n, 5n], // total 140
bombs: {
abomb: [1n],
@@ -71,7 +71,7 @@ describe("Ranking class", () => {
username: "Bob",
stats: {
units: { city: [2n, 0n, 0n, 2n] },
conquests: 8n,
conquests: [8n],
gold: [0n, 50n, 10n, 5n], // total 65, no train trade
bombs: {
abomb: [0n],
@@ -86,7 +86,7 @@ describe("Ranking class", () => {
username: "Charlie",
stats: {
// no units, but has conquests/killedAt to count as played
conquests: 8n,
conquests: [8n],
killedAt: BigInt(600),
gold: [0n, 10n, 2n, 10n, 0n, 5n], // total 27
bombs: {},
@@ -110,21 +110,21 @@ describe("Ranking class", () => {
test("summarizes players correctly", () => {
const r = new Ranking(makeSession());
const players = r.sortedBy(RankType.Conquests);
const players = r.sortedBy(RankType.ConquestHumans);
expect(players.length).toBe(3);
const p1 = players.find((p) => p.id === "p1")!;
expect(p1.username).toBe("Alice");
expect(p1.flag).toBe("USA");
expect(p1.conquests).toBe(5);
expect(p1.conquests).toStrictEqual([5n]);
expect(p1.atoms).toBe(1);
expect(p1.mirv).toBe(2);
});
test("correctly identifies winner", () => {
const r = new Ranking(makeSession());
const p2 = r.sortedBy(RankType.Conquests).find((p) => p.id === "p2")!;
const p2 = r.sortedBy(RankType.ConquestHumans).find((p) => p.id === "p2")!;
expect(p2.winner).toBe(true);
});
@@ -157,7 +157,7 @@ describe("Ranking class", () => {
test("lifetime score is percentage of duration", () => {
const r = new Ranking(makeSession());
const p3 = r.sortedBy(RankType.Conquests).find((p) => p.id === "p3")!;
const p3 = r.sortedBy(RankType.ConquestHumans).find((p) => p.id === "p3")!;
const expected = Number(BigInt(600)) / gameDuration;
expect(r.score(p3, RankType.Lifetime)).toBe(expected);
});
@@ -170,7 +170,7 @@ describe("Ranking class", () => {
test("winners should be ahead of players with same score", () => {
const r = new Ranking(makeSession());
const sortedPlayers = r.sortedBy(RankType.Conquests);
const sortedPlayers = r.sortedBy(RankType.ConquestHumans);
expect(sortedPlayers[0].id).toBe("p2"); // p2 & p3 same score but winner first
});