package storage import ( "testing" "github.com/denisovdennis/autohero/internal/model" ) func TestFilterCapOfferableQuests_filtersTaken(t *testing.T) { all := []model.Quest{ {ID: 1, Title: "a"}, {ID: 2, Title: "b"}, {ID: 3, Title: "c"}, } taken := map[int64]struct{}{2: {}} out := FilterCapOfferableQuests(all, taken, 10, 42) if len(out) != 2 { t.Fatalf("len=%d want 2", len(out)) } for _, q := range out { if q.ID == 2 { t.Fatal("taken quest should be removed") } } } func TestFilterCapOfferableQuests_capDeterministic(t *testing.T) { all := []model.Quest{ {ID: 10, Title: "a"}, {ID: 20, Title: "b"}, {ID: 30, Title: "c"}, } out1 := FilterCapOfferableQuests(all, nil, 2, 999) out2 := FilterCapOfferableQuests(all, nil, 2, 999) if len(out1) != 2 || len(out2) != 2 { t.Fatalf("cap: len1=%d len2=%d", len(out1), len(out2)) } if out1[0].ID != out2[0].ID || out1[1].ID != out2[1].ID { t.Fatalf("same seed should produce same order: %#v vs %#v", out1, out2) } _ = FilterCapOfferableQuests(all, nil, 2, 1000) } func TestFilterCapOfferableQuests_limitZeroReturnsAll(t *testing.T) { all := []model.Quest{{ID: 1}, {ID: 2}} out := FilterCapOfferableQuests(all, nil, 0, 1) if len(out) != 2 { t.Fatalf("len=%d want 2", len(out)) } } func TestQuestOfferDrySpellThisPeriod_edges(t *testing.T) { if QuestOfferDrySpellThisPeriod(1, 2, 3, 0) { t.Fatal("dryChance 0 should never dry") } if !QuestOfferDrySpellThisPeriod(9, 9, 9, 1) { t.Fatal("dryChance 1 should always dry") } a := QuestOfferDrySpellThisPeriod(5, 7, 11, 0.5) b := QuestOfferDrySpellThisPeriod(5, 7, 11, 0.5) if a != b { t.Fatalf("same inputs must match: %v vs %v", a, b) } } func TestQuestOfferDrySpellThisPeriod_distribution(t *testing.T) { var dry int const n = 8000 for b := int64(0); b < n; b++ { if QuestOfferDrySpellThisPeriod(101, 202, b, 0.2) { dry++ } } // Binomial(n=8000,p=0.2): ~99.9% within [0.17,0.23] if dry < int(0.16*float64(n)) || dry > int(0.24*float64(n)) { t.Fatalf("dry count %d out of %d, expected ~20%%", dry, n) } }