package assignment import ( "testing" "doormile/models" ) func cand(id int, inHand, session int64, km, rating float64) *milerCandidate { return &milerCandidate{ profile: models.MilerProfile{Userid: id, Rating: rating}, distanceKm: km, activeBookings: inHand, sessionStops: session, } } // The balancing order: in hand, then this session, then distance, then rating. func TestPickBestBalancesBeforeDistance(t *testing.T) { cases := []struct { name string in []*milerCandidate want int }{ {"fewer in hand beats nearer", []*milerCandidate{cand(1, 2, 0, 0.2, 5), cand(2, 1, 9, 9.0, 1)}, 2}, {"tie in hand: fewer this session", []*milerCandidate{cand(1, 1, 5, 0.2, 5), cand(2, 1, 2, 4.0, 3)}, 2}, {"tie in hand and session: nearer", []*milerCandidate{cand(1, 1, 2, 3.0, 5), cand(2, 1, 2, 1.0, 3)}, 2}, {"full tie: better rating", []*milerCandidate{cand(1, 1, 2, 1.0, 4.1), cand(2, 1, 2, 1.0, 4.8)}, 2}, {"single candidate", []*milerCandidate{cand(7, 3, 3, 3, 3)}, 7}, } for _, c := range cases { if got := pickBestFromCandidates(c.in); got == nil || got.profile.Userid != c.want { t.Errorf("%s: got %v, want rider %d", c.name, got, c.want) } } if pickBestFromCandidates(nil) != nil { t.Error("no candidates must give nil") } } // leastLoaded keeps only the riders with the fewest in hand, with their // parallel AI rows. func TestLeastLoaded(t *testing.T) { cs := []*milerCandidate{cand(1, 2, 0, 1, 4), cand(2, 0, 0, 2, 4), cand(3, 1, 0, 3, 4), cand(4, 0, 5, 4, 4)} ai := []aiCandidate{{MilerID: 1}, {MilerID: 2}, {MilerID: 3}, {MilerID: 4}} gotC, gotAI := leastLoaded(cs, ai) if len(gotC) != 2 || gotC[0].profile.Userid != 2 || gotC[1].profile.Userid != 4 { t.Fatalf("least loaded = %v", gotC) } if len(gotAI) != 2 || gotAI[0].MilerID != 2 || gotAI[1].MilerID != 4 { t.Fatalf("AI rows must follow: %v", gotAI) } if c, a := leastLoaded(nil, nil); len(c) != 0 || len(a) != 0 { t.Fatal("empty in, empty out") } if c, _ := leastLoaded(cs, nil); len(c) != 2 { t.Fatal("AI rows are optional") } }