Add version system, tax tracking, lottery winner DMs, fmtEuro, audit fixes

- Version system: per-plugin versions via Versioned interface, crash_log and
  version_history DB tables, !version command, crash stats in !botinfo
- Tax tracking: tax_ledger table, trackTaxPaid across all communityTax and
  communityPotAdd sites, tax paid display in !stats and !superstatsexplusalpha
- Lottery: DM winners with winning ticket details and matched numbers bolded
- fmtEuro: generic currency formatter with thousand separators across all
  economy display paths
- Audit fixes: streak_decayed column for Streak Survivor achievement,
  combat_narrative empty-phase guard, crafting success rate integer division,
  RecordCrash nil-DB guard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-04-18 01:07:25 -07:00
parent 42e6e23900
commit b15c13cde7
22 changed files with 600 additions and 75 deletions

View File

@@ -4,6 +4,7 @@ import (
"database/sql"
"fmt"
"log/slog"
"math"
"math/rand/v2"
"strings"
"time"
@@ -169,6 +170,29 @@ func communityPotAdd(amount int) {
)
}
func communityTax(userID id.UserID, gross float64, rate float64) (net float64, tax int) {
t := math.Round(gross * rate)
tax = int(t)
net = gross - t
if tax > 0 {
communityPotAdd(tax)
trackTaxPaid(userID, tax)
}
return net, tax
}
func trackTaxPaid(userID id.UserID, amount int) {
if amount <= 0 {
return
}
db.Exec("tax: track paid",
`INSERT INTO tax_ledger (user_id, total_paid, updated_at)
VALUES (?, ?, CURRENT_TIMESTAMP)
ON CONFLICT(user_id) DO UPDATE SET total_paid = total_paid + ?, updated_at = CURRENT_TIMESTAMP`,
string(userID), amount, amount,
)
}
func communityPotBalance() int {
d := db.Get()
var balance int
@@ -556,13 +580,14 @@ func (p *AdventurePlugin) finalizeRivalMatch(challenge *advRivalChallenge, playe
}
}
winnerShare := stake / 2
winnerShare := int(math.Round(float64(stake) * 0.3))
potShare := stake - winnerShare
if winnerShare > 0 {
p.euro.Credit(winnerID, float64(winnerShare), "rival_duel_win")
}
if potShare > 0 {
communityPotAdd(potShare)
trackTaxPaid(loserID, potShare)
}
// Update rival records (both directions).
@@ -672,13 +697,14 @@ func (p *AdventurePlugin) expireRivalChallenges() {
}
}
winnerShare := stake / 2
winnerShare := int(math.Round(float64(stake) * 0.3))
potShare := stake - winnerShare
if winnerShare > 0 {
p.euro.Credit(challenge.ChallengerID, float64(winnerShare), "rival_forfeit_win")
}
if potShare > 0 {
communityPotAdd(potShare)
trackTaxPaid(challenge.ChallengedID, potShare)
}
upsertRivalRecord(challenge.ChallengedID, challenge.ChallengerID, false)