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
3 changes: 3 additions & 0 deletions src/boost/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ func populateArtifactsFromBackup(client dc.Client, userID string) (string, strin
if b := contract.Boosters[userID]; b != nil {
b.ArtifactSet = getUserArtifacts(userID, nil)
rate, logStr := CalculateIHRRateFromDB(userID)
if rate < DefaultLeggyIHR {
rate = DefaultLeggyIHR
}
b.IHRRate = rate
b.IHRCalcLog = logStr
updatedContracts++
Expand Down
10 changes: 10 additions & 0 deletions src/boost/boost.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,9 @@ func AddBoostTokens(client dc.Client, e dc.InteractionEvent, setCountWant int, c
if contract.BoostOrder == ContractOrderIHR || contract.BoostOrder == ContractOrderIHRFuzzy {
for uID, booster := range contract.Boosters {
rate, logStr := CalculateIHRRateFromDB(uID)
if rate < DefaultLeggyIHR {
rate = DefaultLeggyIHR
}
booster.IHRRate = rate
booster.IHRCalcLog = logStr
}
Expand Down Expand Up @@ -747,6 +750,7 @@ func AddFarmerToContract(client dc.Client, contract *Contract, guildID string, c
b.Register = time.Now()
b.UserID = userID
b.Color = 0x00cc00
b.IHRRate = DefaultLeggyIHR

var user, err = client.User(userID)
if err != nil {
Expand Down Expand Up @@ -1265,6 +1269,9 @@ func updateContractFarmerTE(client dc.Client, userID string, b *Booster, contrac
b.IHRCalcLog = fmt.Sprintf("IHR Calculation (Manual for %s): Final=%0.2f", userID, manualIHR)
} else {
rate, logStr := CalculateIHRRateFromBackup(backup, userID)
if rate < DefaultLeggyIHR {
rate = DefaultLeggyIHR
}
b.IHRRate = rate
b.IHRCalcLog = logStr
}
Expand Down Expand Up @@ -1313,6 +1320,9 @@ func updateContractFarmerTE(client dc.Client, userID string, b *Booster, contrac
b.IHRCalcLog = fmt.Sprintf("IHR Calculation (Manual for %s): Final=%0.2f", userID, manualIHR)
} else {
rate, logStr := CalculateIHRRateFromDB(userID)
if rate < DefaultLeggyIHR {
rate = DefaultLeggyIHR
}
b.IHRRate = rate
b.IHRCalcLog = logStr
}
Expand Down
2 changes: 1 addition & 1 deletion src/boost/boost_draw.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ func DrawBoostList(contract *Contract) []dc.LayoutComponent {
sortRate = " **IHR:0** "
}
} else {
sortRate = fmt.Sprintf(" **IHR:%s** ", ei.FormatEIValue(b.IHRRate, map[string]any{"decimals": 2, "trim": true}))
sortRate = fmt.Sprintf(" **IHR:%0.2fx** ", b.IHRRate/DefaultLeggyIHR)
}
}
if (contract.State == ContractStateBanker || contract.State == ContractStateFastrun) && contract.PlayStyle != ContractPlaystyleChill {
Expand Down
45 changes: 45 additions & 0 deletions src/boost/boost_draw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,48 @@ func TestDrawBoostListSkipsUnusableBanner(t *testing.T) {
t.Error("DrawBoostList dropped the media gallery for a usable banner URL")
}
}

func TestDrawBoostListIHRMultiple(t *testing.T) {
contract := &Contract{
ContractHash: "ihr-test-hash",
ContractID: "ihr-test-contract",
CoopID: "ihr-test-coop",
State: ContractStateSignup,
BoostOrder: ContractOrderIHR,
CreatorID: []string{"creator-id"},
Order: []string{"u1", "u2"},
Boosters: map[string]*Booster{
"u1": {
UserID: "u1",
Mention: "<@u1>",
Name: "Player1",
TokensWanted: 6,
IHRRate: 33480.0, // 4.5x 7440.0
},
"u2": {
UserID: "u2",
Mention: "<@u2>",
Name: "Player2",
TokensWanted: 6,
IHRRate: 7440.0, // 1.0x 7440.0
},
},
Location: []*LocationData{{GuildID: "guild1", ChannelID: "channel1"}},
}

components := DrawBoostList(contract)
var outputBuilder strings.Builder
for _, comp := range components {
if textDisplay, ok := comp.(dc.TextDisplay); ok {
outputBuilder.WriteString(textDisplay.Content)
}
}
output := outputBuilder.String()

if !strings.Contains(output, "**IHR:4.50x**") {
t.Errorf("expected output to contain **IHR:4.50x**, got %q", output)
}
if !strings.Contains(output, "**IHR:1.00x**") {
t.Errorf("expected output to contain **IHR:1.00x**, got %q", output)
}
}
5 changes: 4 additions & 1 deletion src/boost/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,10 +829,13 @@ func HandleContractSettingsReactions(client dc.Client, e *dc.ComponentEvent) {
for userID, b := range contract.Boosters {
// Recalculate IHR rate from DB for all boosters so pre-change values excluding deflector stones are updated
rate, logStr := CalculateIHRRateFromDB(userID)
if rate < DefaultLeggyIHR {
rate = DefaultLeggyIHR
}
b.IHRRate = rate
b.IHRCalcLog = logStr

if b.IHRRate == 0 {
if b.IHRRate <= DefaultLeggyIHR {
usersToRefresh = append(usersToRefresh, userToRefresh{userID: userID, booster: b})
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/boost/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1094,3 +1094,36 @@ func TestUpdateThreadName_SkipIfUnchanged(t *testing.T) {
t.Errorf("expected EditChannel with name %q, got: %v", expectedName, edits)
}
}

func TestAddFarmerToContract_MinimumIHR(t *testing.T) {
client := dctest.New().
WithGuild("guild1", "Guild 1").
WithChannel("channel1", "guild1", "contract-channel").
WithUser("user-without-ihr", "farmer_no_ihr", "Farmer No IHR")

contract := &Contract{
ContractHash: "test-hash-ihr-min",
ContractID: "test-contract",
CoopID: "test-coop",
CoopSize: 10,
State: ContractStateSignup,
BoostOrder: ContractOrderSignup,
CreatorID: []string{"creator1"},
Order: make([]string, 0),
Boosters: make(map[string]*Booster),
Location: []*LocationData{{GuildID: "guild1", ChannelID: "channel1"}},
}
Contracts[contract.ContractHash] = contract
defer delete(Contracts, contract.ContractHash)

b, err := AddFarmerToContract(client, contract, "guild1", "channel1", "user-without-ihr", ContractOrderSignup, false, false)
if err != nil {
t.Fatalf("unexpected error adding farmer: %v", err)
}
if b == nil {
t.Fatalf("expected booster to be created, got nil")
}
if b.IHRRate < DefaultLeggyIHR {
t.Errorf("expected b.IHRRate >= %f, got %f", DefaultLeggyIHR, b.IHRRate)
}
}
10 changes: 8 additions & 2 deletions src/boost/update_farmer.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,20 @@ func updateFarmerInContracts(client dc.Client, userID string, subcommand string,
case "te":
booster.TECount = int(value)
rate, logStr := CalculateIHRRateFromDB(userID)
if rate < DefaultLeggyIHR {
rate = DefaultLeggyIHR
}
booster.IHRRate = rate
booster.IHRCalcLog = logStr
case "ihr":
booster.IHRRate = float64(value)
booster.IHRCalcLog = fmt.Sprintf("IHR Calculation (Manual for %s): Final=%0.2f", userID, float64(value))
booster.IHRRate = max(DefaultLeggyIHR, float64(value))
booster.IHRCalcLog = fmt.Sprintf("IHR Calculation (Manual for %s): Final=%0.2f", userID, booster.IHRRate)
case "artifacts":
booster.ArtifactSet = getUserArtifacts(userID, nil)
rate, logStr := CalculateIHRRateFromDB(userID)
if rate < DefaultLeggyIHR {
rate = DefaultLeggyIHR
}
booster.IHRRate = rate
booster.IHRCalcLog = logStr
}
Expand Down
Loading