a geicko-2 based round robin ranking system designed to test c++ battleship submissions
battleship.dunkirk.sh
1package runner
2
3import (
4 "context"
5 "log"
6 "sync"
7 "time"
8
9 "battleship-arena/internal/storage"
10)
11
12var workerMutex sync.Mutex
13
14func StartWorker(ctx context.Context, uploadDir string, broadcastFunc func(string, int, int, time.Time, []string), notifyFunc func(), completeFunc func(), statusFunc func(string, string, string)) {
15 ticker := time.NewTicker(10 * time.Second)
16 defer ticker.Stop()
17
18 go func() {
19 if err := processSubmissionsWithLock(uploadDir, broadcastFunc, notifyFunc, completeFunc, statusFunc); err != nil {
20 log.Printf("Worker error (submissions): %v", err)
21 }
22 }()
23
24 for {
25 select {
26 case <-ctx.Done():
27 return
28 case <-ticker.C:
29 go func() {
30 if err := processSubmissionsWithLock(uploadDir, broadcastFunc, notifyFunc, completeFunc, statusFunc); err != nil {
31 log.Printf("Worker error (submissions): %v", err)
32 }
33 }()
34 }
35 }
36}
37
38func processSubmissionsWithLock(uploadDir string, broadcastFunc func(string, int, int, time.Time, []string), notifyFunc func(), completeFunc func(), statusFunc func(string, string, string)) error {
39 if !workerMutex.TryLock() {
40 // Silently skip if worker is already running
41 return nil
42 }
43 defer workerMutex.Unlock()
44
45 return ProcessSubmissions(uploadDir, broadcastFunc, notifyFunc, completeFunc, statusFunc)
46}
47
48func ProcessSubmissions(uploadDir string, broadcastFunc func(string, int, int, time.Time, []string), notifyFunc func(), completeFunc func(), statusFunc func(string, string, string)) error {
49 submissions, err := storage.GetPendingSubmissions()
50 if err != nil {
51 return err
52 }
53
54 // Only do work if there are pending submissions
55 if len(submissions) == 0 {
56 return nil
57 }
58
59 for _, sub := range submissions {
60 log.Printf("⚙️ Compiling %s (%s)", sub.Username, sub.Filename)
61 statusFunc(sub.Username, "compiling", "")
62
63 if err := CompileSubmission(sub, uploadDir); err != nil {
64 log.Printf("❌ Compilation failed for %s: %v", sub.Username, err)
65 storage.UpdateSubmissionStatusWithMessage(sub.ID, "compilation_failed", err.Error())
66 statusFunc(sub.Username, "compilation_failed", err.Error())
67 notifyFunc()
68 continue
69 }
70
71 log.Printf("✓ Compiled %s", sub.Username)
72 storage.UpdateSubmissionStatus(sub.ID, "completed")
73 statusFunc(sub.Username, "running_matches", "")
74
75 RunRoundRobinMatches(sub, uploadDir, broadcastFunc)
76 statusFunc(sub.Username, "completed", "")
77 notifyFunc()
78 }
79
80 // Check if queue is now empty
81 queuedPlayers := storage.GetQueuedPlayerNames()
82 if len(queuedPlayers) == 0 {
83 completeFunc()
84 }
85
86 return nil
87}