Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 23 additions & 20 deletions src/leaderboard/leaderboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,25 @@ import (

// Leaderboard keys constants.
const (
LBEarningsBonus = "eb"
LBSoulEggs = "soul_eggs"
LBProphecyEggs = "prophecy_eggs"
LBTerrorEvents = "terror_events"
LBEggsDelivered = "eggs_delivered"
LBContractExp = "contract_exp"
LBEggsTotal = "eggs_total"
LBStandardPermit = "std_permit"
LBDrones = "drones"
LBEliteDrones = "elite_drones"
LBPrestiges = "prestiges"
LBSoulMirrors = "soul_mirrors"
LBVirtueShifts = "virtue_shifts"
LBTETotal = "te_total"
LBCTETotal = "cte_total"
LBTEPerShift = "te_per_shift"
LBSEPerPrestige = "se_per_prestige"
LBCXPWeeklyDelta = "cxp_weekly"
LBEarningsBonus = "eb"
LBPrestigedEarningsBonus = "prestiged_eb"
LBSoulEggs = "soul_eggs"
LBProphecyEggs = "prophecy_eggs"
LBTerrorEvents = "terror_events"
LBEggsDelivered = "eggs_delivered"
LBContractExp = "contract_exp"
LBEggsTotal = "eggs_total"
LBStandardPermit = "std_permit"
LBDrones = "drones"
LBEliteDrones = "elite_drones"
LBPrestiges = "prestiges"
LBSoulMirrors = "soul_mirrors"
LBVirtueShifts = "virtue_shifts"
LBTETotal = "te_total"
LBCTETotal = "cte_total"
LBTEPerShift = "te_per_shift"
LBSEPerPrestige = "se_per_prestige"
LBCXPWeeklyDelta = "cxp_weekly"
//LBAAASoloDuration = "aaa_solo_duration"
LBEggsCuriosity = "egg_curiosity"
LBEggsIntegrity = "egg_integrity"
Expand Down Expand Up @@ -110,7 +111,8 @@ type LBGroup struct {
var AllLeaderboards = []LBDef{
{Key: LBSoulEggs, DisplayName: "Soul Eggs", HeaderName: "SE", Description: "Total soul eggs collected.", ValueFmt: "ei", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
{Key: LBProphecyEggs, DisplayName: "Prophecy Eggs", HeaderName: "PE", Description: "Total eggs of prophecy collected.", ValueFmt: "int", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
{Key: LBEarningsBonus, DisplayName: "Earnings Bonus", Description: "Nekkid and Dressed earnings bonus.", ValueFmt: "eb", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
{Key: LBEarningsBonus, DisplayName: "Earnings Bonus", Description: "Nekkid and Dressed earnings bonus (includes pending TE).", ValueFmt: "eb", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
{Key: LBPrestigedEarningsBonus, DisplayName: "Prestiged Earnings Bonus", Description: "Nekkid and Dressed earnings bonus (excludes pending TE).", ValueFmt: "eb", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
{Key: LBVirtueShifts, DisplayName: "Virtue Shifts", HeaderName: "Shifts", Description: "Total virtue shifts completed.", ValueFmt: "int", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
{Key: LBTETotal, DisplayName: "Total Truth Eggs", HeaderName: "TE", Description: "Sum of truth eggs across all virtues.", ValueFmt: "int", HigherIsBetter: true, Source: SourceFirstContact, RetainRecentOnly: true},
{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},
Expand Down Expand Up @@ -140,7 +142,7 @@ var AllGroups = []LBGroup{
{
Key: "group_core",
DisplayName: "EB Stats",
Members: []string{LBEarningsBonus, LBSoulEggs, LBProphecyEggs, LBTETotal, LBCTETotal, LBVirtueShifts, LBPrestiges},
Members: []string{LBEarningsBonus, LBPrestigedEarningsBonus, LBSoulEggs, LBProphecyEggs, LBTETotal, LBCTETotal, LBVirtueShifts, LBPrestiges},
},
{
Key: "group_cs_stats",
Expand Down Expand Up @@ -285,6 +287,7 @@ var legacyKeyAliases = map[string]string{
"cxp_weekly_delta": LBCXPWeeklyDelta,
"group_prestige_stats": "group_misc",
LBVirtueTEEarnedSum: LBVirtueEggsSum,
"eb_prestiged": LBPrestigedEarningsBonus,
}

func resolveAlias(key string) string {
Expand Down
15 changes: 14 additions & 1 deletion src/leaderboard/leaderboard_calculators.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func RunCalculators(
emit(LBEntry{LBType: LBSoulEggs, Player: userID, GameName: gameName, SnapDate: snapDate, Value: game.GetSoulEggsD()})
emit(LBEntry{LBType: LBProphecyEggs, Player: userID, GameName: gameName, SnapDate: snapDate, Value: float64(game.GetEggsOfProphecy())})

// For Earnings Bonus, we need total Truth Eggs (EoV)
// For Earnings Bonus, we need total Truth Eggs (EoV) including pending TE
totalTE := 0.0
if virtue != nil {
deliveries := virtue.GetEggsDelivered()
Expand All @@ -221,6 +221,19 @@ func RunCalculators(
Value: nakedEB,
Details: fmt.Sprintf("dressed:%.6f", dressedEB),
})

// For Prestiged Earnings Bonus, we use credited/prestiged Truth Eggs (excludes pending TE)
prestigedTE := float64(ei.GetCurrentTruthEggs(backup))
prestigedNakedEB := ei.GetEarningsBonus(backup, prestigedTE)
prestigedDressedEB := ei.GetDressedEarningsBonus(backup, prestigedTE)
emit(LBEntry{
LBType: LBPrestigedEarningsBonus,
Player: userID,
GameName: gameName,
SnapDate: snapDate,
Value: prestigedNakedEB,
Details: fmt.Sprintf("dressed:%.6f", prestigedDressedEB),
})
}

if stats != nil {
Expand Down
126 changes: 126 additions & 0 deletions src/leaderboard/leaderboard_calculators_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package leaderboard

import (
"strings"
"testing"

"github.com/mkmccarty/TokenTimeBoostBot/src/ei"
)

func TestRunCalculators_EarningsBonusPendingVsPrestiged(t *testing.T) {
maker := ei.NewBackupMaker("EI1234567890123456", "TestFarmer")
backup := maker.GetBackup()

// 1. With pending TE (eggs delivered passed tiers, but EoV earned = 0)
backup.Virtue = &ei.Backup_Virtue{
EovEarned: []uint32{0},
EggsDelivered: []float64{1e18},
}

entries := RunCalculators(
"user-test-1",
backup,
nil,
[]string{LBEarningsBonus, LBPrestigedEarningsBonus},
"2026-10-12",
0,
)

var entryEB, entryPrestigedEB *LBEntry
for i := range entries {
if entries[i].LBType == LBEarningsBonus {
entryEB = &entries[i]
}
if entries[i].LBType == LBPrestigedEarningsBonus {
entryPrestigedEB = &entries[i]
}
}

if entryEB == nil {
t.Fatalf("expected %s entry to be emitted", LBEarningsBonus)
}
if entryPrestigedEB == nil {
t.Fatalf("expected %s entry to be emitted", LBPrestigedEarningsBonus)
}

if entryEB.Value <= entryPrestigedEB.Value {
t.Errorf("expected Earnings Bonus (%f) to be strictly greater than Prestiged Earnings Bonus (%f) when pending TE > 0",
entryEB.Value, entryPrestigedEB.Value)
}

// 2. Without pending TE (earned TE matches tiers passed)
tiers := ei.CountTruthEggTiersPassed(1e18)
backup.Virtue = &ei.Backup_Virtue{
EovEarned: []uint32{tiers},
EggsDelivered: []float64{1e18},
}

entriesNoPending := RunCalculators(
"user-test-1",
backup,
nil,
[]string{LBEarningsBonus, LBPrestigedEarningsBonus},
"2026-10-12",
0,
)

var entryEB2, entryPrestigedEB2 *LBEntry
for i := range entriesNoPending {
if entriesNoPending[i].LBType == LBEarningsBonus {
entryEB2 = &entriesNoPending[i]
}
if entriesNoPending[i].LBType == LBPrestigedEarningsBonus {
entryPrestigedEB2 = &entriesNoPending[i]
}
}

if entryEB2 == nil || entryPrestigedEB2 == nil {
t.Fatalf("expected both entries to be emitted when no pending TE")
}

if entryEB2.Value != entryPrestigedEB2.Value {
t.Errorf("expected Earnings Bonus (%f) to equal Prestiged Earnings Bonus (%f) when pending TE == 0",
entryEB2.Value, entryPrestigedEB2.Value)
}
}

func TestEarningsBonusRegistryDefinitions(t *testing.T) {
defEB, okEB := LBDefByKey(LBEarningsBonus)
if !okEB {
t.Fatalf("expected definition for %s", LBEarningsBonus)
}
if !strings.Contains(defEB.Description, "pending TE") {
t.Errorf("expected %s description to mention pending TE, got %q", LBEarningsBonus, defEB.Description)
}

defPrestigedEB, okPrestigedEB := LBDefByKey(LBPrestigedEarningsBonus)
if !okPrestigedEB {
t.Fatalf("expected definition for %s", LBPrestigedEarningsBonus)
}
if !strings.Contains(defPrestigedEB.Description, "excludes pending TE") {
t.Errorf("expected %s description to mention excluding pending TE, got %q", LBPrestigedEarningsBonus, defPrestigedEB.Description)
}

// Verify alias
if resolveAlias("eb_prestiged") != LBPrestigedEarningsBonus {
t.Errorf("expected alias eb_prestiged to resolve to %s, got %s", LBPrestigedEarningsBonus, resolveAlias("eb_prestiged"))
}

// Verify group_core contains both
groupCoreMembers := ExpandConfigKey("group_core")
foundEB, foundPrestigedEB := false, false
for _, m := range groupCoreMembers {
if m == LBEarningsBonus {
foundEB = true
}
if m == LBPrestigedEarningsBonus {
foundPrestigedEB = true
}
}
if !foundEB {
t.Errorf("expected %s in group_core members", LBEarningsBonus)
}
if !foundPrestigedEB {
t.Errorf("expected %s in group_core members", LBPrestigedEarningsBonus)
}
}
2 changes: 1 addition & 1 deletion src/leaderboard/leaderboard_post.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ func renderTable(def LBDef, rows []LBEntry, prevMap map[string]float64, rankOffs
rankWidth := runewidth.StringWidth(rankHeader)
maxValOnlyWidth := runewidth.StringWidth(shortDisplayName)

isEB := def.Key == LBEarningsBonus
isEB := def.Key == LBEarningsBonus || def.Key == LBPrestigedEarningsBonus
hasCTEComparisonColumn := def.Key == LBCTETotal
hasTEColumn := def.Key == LBEggsCuriosity || def.Key == LBEggsIntegrity || def.Key == LBEggsHumility || def.Key == LBEggsResilience || def.Key == LBEggsKindness || def.Key == LBVirtueEggsSum
teWidth := runewidth.StringWidth("TE")
Expand Down
4 changes: 2 additions & 2 deletions src/leaderboard/leaderboard_post_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestRenderTable_AllLeaderboards(t *testing.T) {
}

switch {
case def.Key == LBEarningsBonus:
case def.Key == LBEarningsBonus || def.Key == LBPrestigedEarningsBonus:
row.Details = "dressed:23456"
case def.Key == LBCXPWeeklyDelta:
row.Details = "na"
Expand Down Expand Up @@ -127,7 +127,7 @@ func TestRenderTable_AllLeaderboards(t *testing.T) {
}
}

if def.Key == LBEarningsBonus {
if def.Key == LBEarningsBonus || def.Key == LBPrestigedEarningsBonus {
if !strings.Contains(colHeader, "Nekkid") || !strings.Contains(colHeader, "Dressed") {
t.Fatalf("expected EB columns for %s, got %q", def.Key, colHeader)
}
Expand Down
Loading