package httpapi import ( "testing" "git.yeij.top/AskaEth/Scoreboard/server/internal/domain" ) // 分批结算的判据是纯函数,这里逐类钉住它的口径: // 「所有批次都录完」= 该组所有 registered 报名项都有可发布的已发布成绩。 func TestGroupStatsSettlementJudgement(t *testing.T) { value := 11.58 cases := []struct { name string entries []domain.Entry results []domain.Result wantTotal int wantPublished int }{ { name: "全部发完", entries: []domain.Entry{ {ID: 1, Status: domain.EntryStatusRegistered}, {ID: 2, Status: domain.EntryStatusRegistered}, }, results: []domain.Result{ {EntryID: 1, Status: domain.ResultStatusOK, ResultValue: &value, State: domain.ResultStatePublished}, {EntryID: 2, Status: domain.ResultStatusOK, ResultValue: &value, State: domain.ResultStatePublished}, }, wantTotal: 2, wantPublished: 2, }, { name: "有人弃权(scratched 不该再等它)", entries: []domain.Entry{ {ID: 1, Status: domain.EntryStatusRegistered}, {ID: 2, Status: domain.EntryStatusRegistered}, {ID: 3, Status: domain.EntryStatusScratched}, }, results: []domain.Result{ {EntryID: 1, Status: domain.ResultStatusOK, ResultValue: &value, State: domain.ResultStatePublished}, {EntryID: 2, Status: domain.ResultStatusOK, ResultValue: &value, State: domain.ResultStatePublished}, }, wantTotal: 2, wantPublished: 2, }, { name: "有人失格(dq/dns 同样已有现场结论)", entries: []domain.Entry{ {ID: 1, Status: domain.EntryStatusRegistered}, {ID: 2, Status: domain.EntryStatusRegistered}, {ID: 3, Status: domain.EntryStatusDNS}, }, results: []domain.Result{ {EntryID: 1, Status: domain.ResultStatusOK, ResultValue: &value, State: domain.ResultStatePublished}, {EntryID: 2, Status: domain.ResultStatusOK, ResultValue: &value, State: domain.ResultStatePublished}, }, wantTotal: 2, wantPublished: 2, }, { name: "有草稿但不该发布(还没跑 / 还没录)", entries: []domain.Entry{ {ID: 1, Status: domain.EntryStatusRegistered}, {ID: 2, Status: domain.EntryStatusRegistered}, }, results: []domain.Result{ {EntryID: 1, Status: domain.ResultStatusOK, ResultValue: &value, State: domain.ResultStatePublished}, {EntryID: 2, Status: domain.ResultStatusOK, State: domain.ResultStateDraft}, }, wantTotal: 2, wantPublished: 1, }, { name: "已发布但空且 ok 的行不算成绩", entries: []domain.Entry{ {ID: 1, Status: domain.EntryStatusRegistered}, }, results: []domain.Result{ {EntryID: 1, Status: domain.ResultStatusOK, State: domain.ResultStatePublished}, }, wantTotal: 1, wantPublished: 0, }, { name: "DNS 这类没有成绩值的现场结论可以发布", entries: []domain.Entry{ {ID: 1, Status: domain.EntryStatusRegistered}, }, results: []domain.Result{ {EntryID: 1, Status: domain.ResultStatusDNS, State: domain.ResultStatePublished}, }, wantTotal: 1, wantPublished: 1, }, { name: "整组弃权:没有要等的人", entries: []domain.Entry{{ID: 1, Status: domain.EntryStatusScratched}}, results: nil, wantTotal: 0, wantPublished: 0, }, { name: "没有报名项", entries: nil, results: nil, wantTotal: 0, wantPublished: 0, }, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { total, published := groupStats(tc.entries, tc.results) if total != tc.wantTotal || published != tc.wantPublished { t.Fatalf("groupStats = (%d, %d),期望 (%d, %d)", total, published, tc.wantTotal, tc.wantPublished) } got := published == total want := tc.wantPublished == tc.wantTotal if got != want { t.Fatalf("结算判据 = %v,期望 %v", got, want) } }) } } // groupOf 必须只留下该组别的行:成绩表不带组别,靠报名 id 反查时最容易把别组的成绩算进来。 func TestGroupOfFiltersByCategory(t *testing.T) { entries := []domain.Entry{ {ID: 1, CategoryID: 7}, {ID: 2, CategoryID: 7}, {ID: 3, CategoryID: 8}, } results := []domain.Result{ {ID: 11, EntryID: 1}, {ID: 12, EntryID: 2}, {ID: 13, EntryID: 3}, } groupEntries, groupResults := groupOf(entries, results, 7) if len(groupEntries) != 2 || len(groupResults) != 2 { t.Fatalf("第 7 组应只剩 2 条报名 / 2 条成绩,得到 %d / %d", len(groupEntries), len(groupResults)) } for _, r := range groupResults { if r.EntryID == 3 { t.Fatalf("别组的成绩不该被算进来: %+v", r) } } }