Skip to content

Commit 98bdee5

Browse files
committed
feat: add prestiged earnings bonus LB and tests (eb, prestigedeb)
1 parent d4f6d00 commit 98bdee5

5 files changed

Lines changed: 166 additions & 24 deletions

File tree

‎src/leaderboard/leaderboard.go‎

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,25 @@ import (
1717

1818
// Leaderboard keys constants.
1919
const (
20-
LBEarningsBonus = "eb"
21-
LBSoulEggs = "soul_eggs"
22-
LBProphecyEggs = "prophecy_eggs"
23-
LBTerrorEvents = "terror_events"
24-
LBEggsDelivered = "eggs_delivered"
25-
LBContractExp = "contract_exp"
26-
LBEggsTotal = "eggs_total"
27-
LBStandardPermit = "std_permit"
28-
LBDrones = "drones"
29-
LBEliteDrones = "elite_drones"
30-
LBPrestiges = "prestiges"
31-
LBSoulMirrors = "soul_mirrors"
32-
LBVirtueShifts = "virtue_shifts"
33-
LBTETotal = "te_total"
34-
LBCTETotal = "cte_total"
35-
LBTEPerShift = "te_per_shift"
36-
LBSEPerPrestige = "se_per_prestige"
37-
LBCXPWeeklyDelta = "cxp_weekly"
20+
LBEarningsBonus = "eb"
21+
LBPrestigedEarningsBonus = "prestiged_eb"
22+
LBSoulEggs = "soul_eggs"
23+
LBProphecyEggs = "prophecy_eggs"
24+
LBTerrorEvents = "terror_events"
25+
LBEggsDelivered = "eggs_delivered"
26+
LBContractExp = "contract_exp"
27+
LBEggsTotal = "eggs_total"
28+
LBStandardPermit = "std_permit"
29+
LBDrones = "drones"
30+
LBEliteDrones = "elite_drones"
31+
LBPrestiges = "prestiges"
32+
LBSoulMirrors = "soul_mirrors"
33+
LBVirtueShifts = "virtue_shifts"
34+
LBTETotal = "te_total"
35+
LBCTETotal = "cte_total"
36+
LBTEPerShift = "te_per_shift"
37+
LBSEPerPrestige = "se_per_prestige"
38+
LBCXPWeeklyDelta = "cxp_weekly"
3839
//LBAAASoloDuration = "aaa_solo_duration"
3940
LBEggsCuriosity = "egg_curiosity"
4041
LBEggsIntegrity = "egg_integrity"
@@ -110,7 +111,8 @@ type LBGroup struct {
110111
var AllLeaderboards = []LBDef{
111112
{Key: LBSoulEggs, DisplayName: "Soul Eggs", HeaderName: "SE", Description: "Total soul eggs collected.", ValueFmt: "ei", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
112113
{Key: LBProphecyEggs, DisplayName: "Prophecy Eggs", HeaderName: "PE", Description: "Total eggs of prophecy collected.", ValueFmt: "int", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
113-
{Key: LBEarningsBonus, DisplayName: "Earnings Bonus", Description: "Nekkid and Dressed earnings bonus.", ValueFmt: "eb", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
114+
{Key: LBEarningsBonus, DisplayName: "Earnings Bonus", Description: "Nekkid and Dressed earnings bonus (includes pending TE).", ValueFmt: "eb", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
115+
{Key: LBPrestigedEarningsBonus, DisplayName: "Prestiged Earnings Bonus", Description: "Nekkid and Dressed earnings bonus (excludes pending TE).", ValueFmt: "eb", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
114116
{Key: LBVirtueShifts, DisplayName: "Virtue Shifts", HeaderName: "Shifts", Description: "Total virtue shifts completed.", ValueFmt: "int", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
115117
{Key: LBTETotal, DisplayName: "Total Truth Eggs", HeaderName: "TE", Description: "Sum of truth eggs across all virtues.", ValueFmt: "int", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
116118
{Key: LBCTETotal, DisplayName: "Total CTE", HeaderName: "CTE", Description: "Clothed Truth Egg equivalent for pending and current TE.", ValueFmt: "int", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
@@ -140,7 +142,7 @@ var AllGroups = []LBGroup{
140142
{
141143
Key: "group_core",
142144
DisplayName: "EB Stats",
143-
Members: []string{LBEarningsBonus, LBSoulEggs, LBProphecyEggs, LBTETotal, LBCTETotal, LBVirtueShifts, LBPrestiges},
145+
Members: []string{LBEarningsBonus, LBPrestigedEarningsBonus, LBSoulEggs, LBProphecyEggs, LBTETotal, LBCTETotal, LBVirtueShifts, LBPrestiges},
144146
},
145147
{
146148
Key: "group_cs_stats",
@@ -285,6 +287,7 @@ var legacyKeyAliases = map[string]string{
285287
"cxp_weekly_delta": LBCXPWeeklyDelta,
286288
"group_prestige_stats": "group_misc",
287289
LBVirtueTEEarnedSum: LBVirtueEggsSum,
290+
"eb_prestiged": LBPrestigedEarningsBonus,
288291
}
289292

290293
func resolveAlias(key string) string {

‎src/leaderboard/leaderboard_calculators.go‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func RunCalculators(
203203
emit(LBEntry{LBType: LBSoulEggs, Player: userID, GameName: gameName, SnapDate: snapDate, Value: game.GetSoulEggsD()})
204204
emit(LBEntry{LBType: LBProphecyEggs, Player: userID, GameName: gameName, SnapDate: snapDate, Value: float64(game.GetEggsOfProphecy())})
205205

206-
// For Earnings Bonus, we need total Truth Eggs (EoV)
206+
// For Earnings Bonus, we need total Truth Eggs (EoV) including pending TE
207207
totalTE := 0.0
208208
if virtue != nil {
209209
deliveries := virtue.GetEggsDelivered()
@@ -221,6 +221,19 @@ func RunCalculators(
221221
Value: nakedEB,
222222
Details: fmt.Sprintf("dressed:%.6f", dressedEB),
223223
})
224+
225+
// For Prestiged Earnings Bonus, we use credited/prestiged Truth Eggs (excludes pending TE)
226+
prestigedTE := float64(ei.GetCurrentTruthEggs(backup))
227+
prestigedNakedEB := ei.GetEarningsBonus(backup, prestigedTE)
228+
prestigedDressedEB := ei.GetDressedEarningsBonus(backup, prestigedTE)
229+
emit(LBEntry{
230+
LBType: LBPrestigedEarningsBonus,
231+
Player: userID,
232+
GameName: gameName,
233+
SnapDate: snapDate,
234+
Value: prestigedNakedEB,
235+
Details: fmt.Sprintf("dressed:%.6f", prestigedDressedEB),
236+
})
224237
}
225238

226239
if stats != nil {
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package leaderboard
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/mkmccarty/TokenTimeBoostBot/src/ei"
8+
)
9+
10+
func TestRunCalculators_EarningsBonusPendingVsPrestiged(t *testing.T) {
11+
maker := ei.NewBackupMaker("EI1234567890123456", "TestFarmer")
12+
backup := maker.GetBackup()
13+
14+
// 1. With pending TE (eggs delivered passed tiers, but EoV earned = 0)
15+
backup.Virtue = &ei.Backup_Virtue{
16+
EovEarned: []uint32{0},
17+
EggsDelivered: []float64{1e18},
18+
}
19+
20+
entries := RunCalculators(
21+
"user-test-1",
22+
backup,
23+
nil,
24+
[]string{LBEarningsBonus, LBPrestigedEarningsBonus},
25+
"2026-10-12",
26+
0,
27+
)
28+
29+
var entryEB, entryPrestigedEB *LBEntry
30+
for i := range entries {
31+
if entries[i].LBType == LBEarningsBonus {
32+
entryEB = &entries[i]
33+
}
34+
if entries[i].LBType == LBPrestigedEarningsBonus {
35+
entryPrestigedEB = &entries[i]
36+
}
37+
}
38+
39+
if entryEB == nil {
40+
t.Fatalf("expected %s entry to be emitted", LBEarningsBonus)
41+
}
42+
if entryPrestigedEB == nil {
43+
t.Fatalf("expected %s entry to be emitted", LBPrestigedEarningsBonus)
44+
}
45+
46+
if entryEB.Value <= entryPrestigedEB.Value {
47+
t.Errorf("expected Earnings Bonus (%f) to be strictly greater than Prestiged Earnings Bonus (%f) when pending TE > 0",
48+
entryEB.Value, entryPrestigedEB.Value)
49+
}
50+
51+
// 2. Without pending TE (earned TE matches tiers passed)
52+
tiers := ei.CountTruthEggTiersPassed(1e18)
53+
backup.Virtue = &ei.Backup_Virtue{
54+
EovEarned: []uint32{tiers},
55+
EggsDelivered: []float64{1e18},
56+
}
57+
58+
entriesNoPending := RunCalculators(
59+
"user-test-1",
60+
backup,
61+
nil,
62+
[]string{LBEarningsBonus, LBPrestigedEarningsBonus},
63+
"2026-10-12",
64+
0,
65+
)
66+
67+
var entryEB2, entryPrestigedEB2 *LBEntry
68+
for i := range entriesNoPending {
69+
if entriesNoPending[i].LBType == LBEarningsBonus {
70+
entryEB2 = &entriesNoPending[i]
71+
}
72+
if entriesNoPending[i].LBType == LBPrestigedEarningsBonus {
73+
entryPrestigedEB2 = &entriesNoPending[i]
74+
}
75+
}
76+
77+
if entryEB2 == nil || entryPrestigedEB2 == nil {
78+
t.Fatalf("expected both entries to be emitted when no pending TE")
79+
}
80+
81+
if entryEB2.Value != entryPrestigedEB2.Value {
82+
t.Errorf("expected Earnings Bonus (%f) to equal Prestiged Earnings Bonus (%f) when pending TE == 0",
83+
entryEB2.Value, entryPrestigedEB2.Value)
84+
}
85+
}
86+
87+
func TestEarningsBonusRegistryDefinitions(t *testing.T) {
88+
defEB, okEB := LBDefByKey(LBEarningsBonus)
89+
if !okEB {
90+
t.Fatalf("expected definition for %s", LBEarningsBonus)
91+
}
92+
if !strings.Contains(defEB.Description, "pending TE") {
93+
t.Errorf("expected %s description to mention pending TE, got %q", LBEarningsBonus, defEB.Description)
94+
}
95+
96+
defPrestigedEB, okPrestigedEB := LBDefByKey(LBPrestigedEarningsBonus)
97+
if !okPrestigedEB {
98+
t.Fatalf("expected definition for %s", LBPrestigedEarningsBonus)
99+
}
100+
if !strings.Contains(defPrestigedEB.Description, "excludes pending TE") {
101+
t.Errorf("expected %s description to mention excluding pending TE, got %q", LBPrestigedEarningsBonus, defPrestigedEB.Description)
102+
}
103+
104+
// Verify alias
105+
if resolveAlias("eb_prestiged") != LBPrestigedEarningsBonus {
106+
t.Errorf("expected alias eb_prestiged to resolve to %s, got %s", LBPrestigedEarningsBonus, resolveAlias("eb_prestiged"))
107+
}
108+
109+
// Verify group_core contains both
110+
groupCoreMembers := ExpandConfigKey("group_core")
111+
foundEB, foundPrestigedEB := false, false
112+
for _, m := range groupCoreMembers {
113+
if m == LBEarningsBonus {
114+
foundEB = true
115+
}
116+
if m == LBPrestigedEarningsBonus {
117+
foundPrestigedEB = true
118+
}
119+
}
120+
if !foundEB {
121+
t.Errorf("expected %s in group_core members", LBEarningsBonus)
122+
}
123+
if !foundPrestigedEB {
124+
t.Errorf("expected %s in group_core members", LBPrestigedEarningsBonus)
125+
}
126+
}

‎src/leaderboard/leaderboard_post.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,7 @@ func renderTable(def LBDef, rows []LBEntry, prevMap map[string]float64, rankOffs
696696
rankWidth := runewidth.StringWidth(rankHeader)
697697
maxValOnlyWidth := runewidth.StringWidth(shortDisplayName)
698698

699-
isEB := def.Key == LBEarningsBonus
699+
isEB := def.Key == LBEarningsBonus || def.Key == LBPrestigedEarningsBonus
700700
hasCTEComparisonColumn := def.Key == LBCTETotal
701701
hasTEColumn := def.Key == LBEggsCuriosity || def.Key == LBEggsIntegrity || def.Key == LBEggsHumility || def.Key == LBEggsResilience || def.Key == LBEggsKindness || def.Key == LBVirtueEggsSum
702702
teWidth := runewidth.StringWidth("TE")

‎src/leaderboard/leaderboard_post_test.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func TestRenderTable_AllLeaderboards(t *testing.T) {
5050
}
5151

5252
switch {
53-
case def.Key == LBEarningsBonus:
53+
case def.Key == LBEarningsBonus || def.Key == LBPrestigedEarningsBonus:
5454
row.Details = "dressed:23456"
5555
case def.Key == LBCXPWeeklyDelta:
5656
row.Details = "na"
@@ -127,7 +127,7 @@ func TestRenderTable_AllLeaderboards(t *testing.T) {
127127
}
128128
}
129129

130-
if def.Key == LBEarningsBonus {
130+
if def.Key == LBEarningsBonus || def.Key == LBPrestigedEarningsBonus {
131131
if !strings.Contains(colHeader, "Nekkid") || !strings.Contains(colHeader, "Dressed") {
132132
t.Fatalf("expected EB columns for %s, got %q", def.Key, colHeader)
133133
}

0 commit comments

Comments
 (0)