From 5126e0fd77e6de74fc5c466ff245887db4dda646 Mon Sep 17 00:00:00 2001 From: Luca <30503695+tameTNT@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:56:57 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=97=EF=B8=8F=20Remove=20concept=20of?= =?UTF-8?q?=20unranked=20projects=20and=20move=20to=20batch=20submission?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Towards addressing issue #1. Under the new system (not yet developed) unranked teams will not exist and rankings will be submitted in batches. --- client/src/components/judge/ProjectEntry.tsx | 2 +- client/src/pages/admin/settings.tsx | 43 +++++++++++++++++++- client/src/pages/judge/index.tsx | 28 +++++++++++-- client/src/types.d.ts | 1 + server/models/options.go | 24 ++++++----- server/ranking/borda.go | 12 +++--- server/ranking/borda_test.go | 8 ++-- server/router/admin.go | 13 +++--- 8 files changed, 97 insertions(+), 34 deletions(-) diff --git a/client/src/components/judge/ProjectEntry.tsx b/client/src/components/judge/ProjectEntry.tsx index 7645b3b..1950528 100644 --- a/client/src/components/judge/ProjectEntry.tsx +++ b/client/src/components/judge/ProjectEntry.tsx @@ -18,7 +18,7 @@ const ProjectEntry = ({ project }: ProjectEntryProps) => { if (project.id === -1) { return (
-

Unsorted Projects below here...

+

Unranked projects below here...

); } diff --git a/client/src/pages/admin/settings.tsx b/client/src/pages/admin/settings.tsx index a0532c9..72df2f0 100644 --- a/client/src/pages/admin/settings.tsx +++ b/client/src/pages/admin/settings.tsx @@ -23,6 +23,7 @@ const AdminSettings = () => { const [dropPopup, setDropPopup] = useState(false); const [judgingTimer, setJudgingTimer] = useState(''); const [categories, setCategories] = useState(''); + const [rankingBatchSize, setRankingBatchSize] = useState(8); const [loading, setLoading] = useState(true); async function getOptions() { @@ -45,6 +46,10 @@ const AdminSettings = () => { const cats = res.data?.categories.join(', '); setCategories(cats ?? ''); + // Set ranking batch size + const rbs = res.data?.ranking_batch_size; + setRankingBatchSize(rbs ?? 8) + setLoading(false); } @@ -111,6 +116,19 @@ const AdminSettings = () => { getOptions(); }; + const updateRankingBatchSize = async () => { + const res = await postRequest('/admin/categories', 'admin', { + ranking_batch_size: rankingBatchSize, + }); + if (res.status !== 200 || res.data?.ok !== 1) { + errorAlert(res); + return; + } + + alert('Ranking Batch Size updated!'); + getOptions(); + } + const resetClock = async () => { const res = await postRequest('/admin/clock/reset', 'admin', null); if (res.status !== 200 || res.data?.ok !== 1) { @@ -234,11 +252,34 @@ const AdminSettings = () => { + Set Ranking Batch Size + + Set how many projects judges rank at a time (must be at least 2 obviously). + Judges can rank and reorder projects freely before submitting a batch of the specified size. + + { + setRankingBatchSize(parseInt(e.target.value)); + }} + /> + +
Project Numbers
Reassign Project Numbers diff --git a/client/src/pages/judge/index.tsx b/client/src/pages/judge/index.tsx index e40f952..590a938 100644 --- a/client/src/pages/judge/index.tsx +++ b/client/src/pages/judge/index.tsx @@ -30,6 +30,7 @@ const Judge = () => { const navigate = useNavigate(); const [judge, setJudge] = useState(null); const [projects, setProjects] = useState([]); + const [allRanked, setAllRanked] = useState(false) const [loaded, setLoaded] = useState(false); const [projCount, setProjCount] = useState(0); const [activeId, setActiveId] = useState(null); @@ -125,6 +126,8 @@ const Judge = () => { const combinedProjects = [...rankedProjects, dummy, ...unrankedProjects]; setProjects(combinedProjects); + setAllRanked(rankedProjects.length === 3); // lucatodo: use rank batch size variable; + // lucatodo: rankedProjects won't be variable we want to find length of. new variable probable: batchProjects? setLoaded(true); }, [judge]); @@ -169,6 +172,7 @@ const Judge = () => { const saveSort = async (newProjects: SortableJudgedProject[]) => { // Split index const splitIndex = newProjects.findIndex((p) => p.id === -1); + setAllRanked(newProjects.length>0 && splitIndex === newProjects.length-1); // lucatodo: use rank batch size variable equality, not >0 // Get the ranked projects const rankedProjects = newProjects.slice(0, splitIndex); @@ -189,6 +193,7 @@ const Judge = () => {

Welcome, {judge?.name}!

+ {/* lucatodo: disable button if all projects in batch seen */} @@ -199,10 +204,12 @@ const Judge = () => {
- - + +

Rank Projects

+ {/* lucatodo: only update scores on submission? query this (only relevant if prioritisation implemented, issue #5 */} +

NB: Relative project order is tracked on the admin panel even before your submit a batch.

{ > {projects.map((item) => ( - + ))} {activeId ? ( - p.id === activeId)} /> + p.id === activeId)}/> ) : null} +
+
+ {/* lucatodo: update X with variable limit */} + {/* lucatodo: text updates if judging is ended manually to allow 'early' submission (see issue #4) */} + Please rank all your projects.
+ You can only submit rankings in batches of X projects. +
+ +
); diff --git a/client/src/types.d.ts b/client/src/types.d.ts index 78a87c2..ce372f2 100644 --- a/client/src/types.d.ts +++ b/client/src/types.d.ts @@ -112,6 +112,7 @@ interface Options { clock: ClockState; judging_timer: number; categories: string[]; + ranking_batch_size: number; } interface FetchResponse { diff --git a/server/models/options.go b/server/models/options.go index 679ab0d..e09217b 100644 --- a/server/models/options.go +++ b/server/models/options.go @@ -3,20 +3,22 @@ package models import "go.mongodb.org/mongo-driver/bson/primitive" type Options struct { - Id primitive.ObjectID `bson:"_id,omitempty" json:"id"` - Ref int64 `bson:"ref" json:"ref"` - CurrTableNum int64 `bson:"curr_table_num" json:"curr_table_num"` - Clock ClockState `bson:"clock" json:"clock"` - JudgingTimer int64 `bson:"judging_timer" json:"judging_timer"` - Categories []string `bson:"categories" json:"categories"` + Id primitive.ObjectID `bson:"_id,omitempty" json:"id"` + Ref int64 `bson:"ref" json:"ref"` + CurrTableNum int64 `bson:"curr_table_num" json:"curr_table_num"` + Clock ClockState `bson:"clock" json:"clock"` + JudgingTimer int64 `bson:"judging_timer" json:"judging_timer"` + Categories []string `bson:"categories" json:"categories"` + RankingBatchSize int64 `bson:"ranking_batch_size" json:"ranking_batch_size"` } func NewOptions() *Options { return &Options{ - Ref: 0, - CurrTableNum: 0, - JudgingTimer: 300, - Clock: *NewClockState(), - Categories: []string{"Creativity/Innovation", "Technical Competence/Execution", "Research/Design", "Presentation"}, + Ref: 0, + CurrTableNum: 0, + JudgingTimer: 300, + Clock: *NewClockState(), + Categories: []string{"Creativity/Innovation", "Technical Competence/Execution", "Research/Design", "Presentation"}, + RankingBatchSize: 8, } } diff --git a/server/ranking/borda.go b/server/ranking/borda.go index 2953066..6d904db 100644 --- a/server/ranking/borda.go +++ b/server/ranking/borda.go @@ -8,7 +8,7 @@ import ( type JudgeRanking struct { Rankings []primitive.ObjectID `json:"rankings"` - Unranked []primitive.ObjectID `json:"unranked"` + //Unranked []primitive.ObjectID `json:"unranked"` } type RankedObject struct { @@ -34,11 +34,11 @@ func rankingToPairwise(judgeRanking JudgeRanking) []Comparison { } // Loop through each project in the ranking and compare it to all the unranked projects - for _, winner := range judgeRanking.Rankings { - for _, loser := range judgeRanking.Unranked { - pairwise = append(pairwise, Comparison{winner, loser}) - } - } + //for _, winner := range judgeRanking.Rankings { + // for _, loser := range judgeRanking.Unranked { + // pairwise = append(pairwise, Comparison{winner, loser}) + // } + //} return pairwise } diff --git a/server/ranking/borda_test.go b/server/ranking/borda_test.go index 3264389..d3f6e63 100644 --- a/server/ranking/borda_test.go +++ b/server/ranking/borda_test.go @@ -19,19 +19,19 @@ func TestCalcRanking(t *testing.T) { jrs := []ranking.JudgeRanking{ { Rankings: []primitive.ObjectID{obj1, obj5, obj3}, - Unranked: []primitive.ObjectID{obj4, obj2}, + //Unranked: []primitive.ObjectID{obj4, obj2}, }, { Rankings: []primitive.ObjectID{obj5, obj4, obj2}, - Unranked: []primitive.ObjectID{obj3, obj1}, + //Unranked: []primitive.ObjectID{obj3, obj1}, }, { Rankings: []primitive.ObjectID{obj1, obj5, obj2}, - Unranked: []primitive.ObjectID{obj3, obj4}, + //Unranked: []primitive.ObjectID{obj3, obj4}, }, { Rankings: []primitive.ObjectID{obj2, obj1, obj5}, - Unranked: []primitive.ObjectID{obj5, obj3}, + //Unranked: []primitive.ObjectID{obj5, obj3}, }, } diff --git a/server/router/admin.go b/server/router/admin.go index 3cb7fa0..134d6e6 100644 --- a/server/router/admin.go +++ b/server/router/admin.go @@ -393,16 +393,15 @@ func GetScores(ctx *gin.Context) { // Create an array of {Rankings: [], Unranked: []} judgeRankings := make([]ranking.JudgeRanking, 0) for _, judge := range judges { - unranked := make([]primitive.ObjectID, 0) - for _, proj := range judge.SeenProjects { - if !contains(judge.Rankings, proj.ProjectId) { - unranked = append(unranked, proj.ProjectId) - } - } + //for _, proj := range judge.SeenProjects { + // if !contains(judge.Rankings, proj.ProjectId) { + // unranked = append(unranked, proj.ProjectId) + // } + //} judgeRankings = append(judgeRankings, ranking.JudgeRanking{ Rankings: judge.Rankings, - Unranked: unranked, + //Unranked: unranked, }) }