mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 16:42:41 +00:00
- Add forex plugin (Frankfurter v2 API) with rate lookups, analysis, DM-based alerts, and daily cron poll. Backfills 1 year of history on startup for moving averages and buy signal scoring. - Fix bot hang caused by SQLite lock contention in reminder polling: rows cursor was held open while writing to the same DB. Collect results first, close cursor, then process. Same fix in milkcarton. - Add sync retry loop so the bot reconnects after network drops instead of silently exiting. StopSync() for clean Ctrl+C shutdown. - Add panic recovery to all dispatch, syncer, and cron paths. - Make all HTTP-calling plugin commands async (goroutines) so a slow or dead external API cannot block the message dispatch pipeline. Affects: lookup, stocks, forex, anime, movies, concerts, gaming, retro, wotd, urls, howami. - Extract DisplayName to Base, add db.Exec helper, convert silent error discards across the codebase. - Fix UNO mercy-kill bug (eliminated bot continues playing), adventure DM nag spam, stats column mismatch, per-call regex/replacer allocs. - Update README: forex commands, Finance section, 47 plugins. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
89 lines
2.2 KiB
Go
89 lines
2.2 KiB
Go
package plugin
|
|
|
|
import "testing"
|
|
|
|
func TestHandValue_SimpleHand(t *testing.T) {
|
|
cards := []card{{Rank: 10, Suit: spades}, {Rank: 7, Suit: hearts}}
|
|
val, soft := handValue(cards)
|
|
if val != 17 || soft {
|
|
t.Errorf("got %d soft=%v, want 17 soft=false", val, soft)
|
|
}
|
|
}
|
|
|
|
func TestHandValue_AceAsSoft(t *testing.T) {
|
|
cards := []card{{Rank: 1, Suit: spades}, {Rank: 6, Suit: hearts}}
|
|
val, soft := handValue(cards)
|
|
if val != 17 || !soft {
|
|
t.Errorf("got %d soft=%v, want 17 soft=true", val, soft)
|
|
}
|
|
}
|
|
|
|
func TestHandValue_AceDowngradesToOne(t *testing.T) {
|
|
cards := []card{
|
|
{Rank: 1, Suit: spades},
|
|
{Rank: 9, Suit: hearts},
|
|
{Rank: 5, Suit: diamonds},
|
|
}
|
|
val, soft := handValue(cards)
|
|
// A(11)+9+5 = 25, bust, so A=1: 1+9+5 = 15
|
|
if val != 15 || soft {
|
|
t.Errorf("got %d soft=%v, want 15 soft=false", val, soft)
|
|
}
|
|
}
|
|
|
|
func TestHandValue_TwoAces(t *testing.T) {
|
|
cards := []card{
|
|
{Rank: 1, Suit: spades},
|
|
{Rank: 1, Suit: hearts},
|
|
}
|
|
val, soft := handValue(cards)
|
|
// A(11)+A(11) = 22, one A->1: 12, still soft
|
|
if val != 12 || !soft {
|
|
t.Errorf("got %d soft=%v, want 12 soft=true", val, soft)
|
|
}
|
|
}
|
|
|
|
func TestHandValue_FaceCards(t *testing.T) {
|
|
cards := []card{{Rank: 11, Suit: spades}, {Rank: 12, Suit: hearts}} // J + Q
|
|
val, soft := handValue(cards)
|
|
if val != 20 || soft {
|
|
t.Errorf("got %d soft=%v, want 20 soft=false", val, soft)
|
|
}
|
|
}
|
|
|
|
func TestHandValue_Bust(t *testing.T) {
|
|
cards := []card{
|
|
{Rank: 10, Suit: spades},
|
|
{Rank: 8, Suit: hearts},
|
|
{Rank: 5, Suit: diamonds},
|
|
}
|
|
val, _ := handValue(cards)
|
|
if val != 23 {
|
|
t.Errorf("got %d, want 23 (bust)", val)
|
|
}
|
|
}
|
|
|
|
func TestIsBlackjack(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cards []card
|
|
want bool
|
|
}{
|
|
{"ace+king", []card{{1, spades}, {13, hearts}}, true},
|
|
{"ace+ten", []card{{1, spades}, {10, hearts}}, true},
|
|
{"ace+queen", []card{{1, spades}, {12, hearts}}, true},
|
|
{"ten+jack", []card{{10, spades}, {11, hearts}}, false}, // 20, not 21
|
|
{"three cards summing 21", []card{{7, spades}, {7, hearts}, {7, diamonds}}, false},
|
|
{"ace+five", []card{{1, spades}, {5, hearts}}, false}, // 16
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := isBlackjack(tt.cards)
|
|
if got != tt.want {
|
|
t.Errorf("isBlackjack(%v) = %v, want %v", tt.cards, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|