Skip to content

Commit 3d22372

Browse files
Implemented Team Debates with Elo Averaging, Team Channels, and Fair Turn Management
Implemented Team Debates with Elo Averaging, Team Channels, and Fair Turn Management Merge pull request #116 from rixitgithub/f/rishit-team-debates
2 parents 655656a + 4ccc4e7 commit 3d22372

File tree

16 files changed

+1390
-236
lines changed

16 files changed

+1390
-236
lines changed

backend/controllers/team_controller.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,15 @@ func JoinTeam(c *gin.Context) {
366366
for _, member := range team.Members {
367367
totalElo += member.Elo
368368
}
369+
<<<<<<< HEAD
370+
if len(team.Members) >= team.MaxSize {
371+
=======
369372
capacity := team.MaxSize
370373
if capacity <= 0 {
371374
capacity = 4
372375
}
373376
if len(team.Members) >= capacity {
377+
>>>>>>> main
374378
c.JSON(http.StatusBadRequest, gin.H{"error": "Team is already full"})
375379
return
376380
}
@@ -626,11 +630,19 @@ func GetAvailableTeams(c *gin.Context) {
626630
collection := db.GetCollection("teams")
627631
cursor, err := collection.Find(context.Background(), bson.M{
628632
"$expr": bson.M{
633+
<<<<<<< HEAD
634+
"$lt": []interface{}{
635+
bson.M{"$size": "$members"},
636+
"$maxSize",
637+
},
638+
},
639+
=======
629640
"$lt": bson.A{
630641
bson.M{"$size": "$members"},
631642
"$maxSize",
632643
},
633644
},
645+
>>>>>>> main
634646
})
635647
if err != nil {
636648
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve teams"})

backend/controllers/team_matchmaking.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controllers
33
import (
44
"context"
55
"net/http"
6+
"time"
67

78
"arguehub/db"
89
"arguehub/models"
@@ -32,7 +33,9 @@ func JoinMatchmaking(c *gin.Context) {
3233
// Get team
3334
collection := db.GetCollection("teams")
3435
var team models.Team
35-
err = collection.FindOne(context.Background(), bson.M{"_id": objectID}).Decode(&team)
36+
ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second)
37+
defer cancel()
38+
err = collection.FindOne(ctx, bson.M{"_id": objectID}).Decode(&team)
3639
if err != nil {
3740
c.JSON(http.StatusNotFound, gin.H{"error": "Team not found"})
3841
return
@@ -85,14 +88,16 @@ func LeaveMatchmaking(c *gin.Context) {
8588

8689
collection := db.GetCollection("teams")
8790
var team models.Team
88-
if err := collection.FindOne(context.Background(), bson.M{"_id": objectID}).Decode(&team); err != nil {
91+
ctxLeave, cancelLeave := context.WithTimeout(c.Request.Context(), 5*time.Second)
92+
defer cancelLeave()
93+
if err := collection.FindOne(ctxLeave, bson.M{"_id": objectID}).Decode(&team); err != nil {
8994
c.JSON(http.StatusNotFound, gin.H{"error": "Team not found"})
9095
return
9196
}
9297

9398
userObjectID, ok := userID.(primitive.ObjectID)
9499
if !ok || team.CaptainID != userObjectID {
95-
c.JSON(http.StatusForbidden, gin.H{"error": "Only the captain can remove the team from matchmaking"})
100+
c.JSON(http.StatusForbidden, gin.H{"error": "Only the captain can leave matchmaking"})
96101
return
97102
}
98103

backend/middlewares/auth.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/gin-gonic/gin"
1616
"github.com/golang-jwt/jwt/v5"
1717
"go.mongodb.org/mongo-driver/bson"
18+
"go.mongodb.org/mongo-driver/mongo"
1819
)
1920

2021
func AuthMiddleware(configPath string) gin.HandlerFunc {
@@ -62,10 +63,16 @@ func AuthMiddleware(configPath string) gin.HandlerFunc {
6263
return
6364
}
6465

65-
email := claims["sub"].(string)
66+
email, ok := claims["sub"].(string)
67+
if !ok || email == "" {
68+
log.Printf("Invalid or missing 'sub' claim in JWT")
69+
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"})
70+
c.Abort()
71+
return
72+
}
6673

6774
// Fetch user from database
68-
dbCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
75+
dbCtx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second)
6976
defer cancel()
7077

7178
if db.MongoDatabase == nil {
@@ -77,7 +84,12 @@ func AuthMiddleware(configPath string) gin.HandlerFunc {
7784
var user models.User
7885
err = db.MongoDatabase.Collection("users").FindOne(dbCtx, bson.M{"email": email}).Decode(&user)
7986
if err != nil {
80-
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not found"})
87+
if errors.Is(err, mongo.ErrNoDocuments) {
88+
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not found"})
89+
} else {
90+
log.Printf("Failed to load user %s: %v", email, err)
91+
c.JSON(http.StatusInternalServerError, gin.H{"error": "Authentication lookup failed"})
92+
}
8193
c.Abort()
8294
return
8395
}

backend/models/team.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,22 @@ type TeamChatMessage struct {
108108
// MarshalJSON customizes JSON serialization for TeamDebate to convert ObjectIDs to hex strings
109109
func (td TeamDebate) MarshalJSON() ([]byte, error) {
110110
type Alias TeamDebate
111+
var currentUserHex *string
112+
if !td.CurrentUserID.IsZero() {
113+
hex := td.CurrentUserID.Hex()
114+
currentUserHex = &hex
115+
}
111116
return json.Marshal(&struct {
112-
ID string `json:"id,omitempty"`
113-
Team1ID string `json:"team1Id"`
114-
Team2ID string `json:"team2Id"`
115-
CurrentUserID string `json:"currentUserId,omitempty"`
117+
ID string `json:"id,omitempty"`
118+
Team1ID string `json:"team1Id"`
119+
Team2ID string `json:"team2Id"`
120+
CurrentUserID *string `json:"currentUserId,omitempty"`
116121
*Alias
117122
}{
118123
ID: td.ID.Hex(),
119124
Team1ID: td.Team1ID.Hex(),
120125
Team2ID: td.Team2ID.Hex(),
121-
CurrentUserID: func() string {
122-
if td.CurrentUserID.IsZero() {
123-
return ""
124-
}
125-
return td.CurrentUserID.Hex()
126-
}(),
126+
CurrentUserID: currentUserHex,
127127
Alias: (*Alias)(&td),
128128
})
129129
}

backend/services/team_matchmaking.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ func StartTeamMatchmaking(teamID primitive.ObjectID) error {
3131
// Get team details
3232
collection := db.GetCollection("teams")
3333
var team models.Team
34-
err := collection.FindOne(context.Background(), bson.M{"_id": teamID}).Decode(&team)
34+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
35+
defer cancel()
36+
err := collection.FindOne(ctx, bson.M{"_id": teamID}).Decode(&team)
3537
if err != nil {
3638
return err
3739
}
@@ -66,7 +68,7 @@ func FindMatchingTeam(lookingTeamID primitive.ObjectID) (*models.Team, error) {
6668
defer teamMatchmakingMutex.RUnlock()
6769

6870
if teamMatchmakingPool == nil {
69-
teamMatchmakingPool = make(map[string]*TeamMatchmakingEntry)
71+
return nil, mongo.ErrNoDocuments
7072
}
7173

7274
lookingEntry, exists := teamMatchmakingPool[lookingTeamID.Hex()]
@@ -116,8 +118,9 @@ func GetMatchmakingPool() map[string]*TeamMatchmakingEntry {
116118
return make(map[string]*TeamMatchmakingEntry)
117119
}
118120
snapshot := make(map[string]*TeamMatchmakingEntry, len(teamMatchmakingPool))
119-
for id, entry := range teamMatchmakingPool {
120-
snapshot[id] = entry
121+
for teamID, entry := range teamMatchmakingPool {
122+
clone := *entry
123+
snapshot[teamID] = &clone
121124
}
122125
return snapshot
123126
}

backend/websocket/team_debate_handler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package websocket
22

33
import (
4+
"context"
45
"encoding/json"
56
"time"
67

@@ -61,7 +62,7 @@ func TeamDebateHubRun() {
6162
// Load debate from database
6263
collection := db.GetCollection("team_debates")
6364
var debate models.TeamDebate
64-
err := collection.FindOne(nil, bson.M{"_id": client.debateID}).Decode(&debate)
65+
err := collection.FindOne(context.Background(), bson.M{"_id": client.debateID}).Decode(&debate)
6566
if err == nil {
6667
room = &TeamDebateRoom{
6768
debate: debate,
@@ -79,7 +80,6 @@ func TeamDebateHubRun() {
7980
room.team2Clients[client] = true
8081
}
8182

82-
// Send current debate state to new client
8383
room.broadcastToTeam(client, TeamDebateMessage{
8484
Type: "state",
8585
Data: room.debate,
@@ -194,7 +194,7 @@ func (c *TeamDebateClient) readPump() {
194194
Timestamp: time.Now(),
195195
}
196196

197-
_, err := collection.InsertOne(nil, msg)
197+
_, err := collection.InsertOne(context.Background(), msg)
198198
if err != nil {
199199
}
200200

0 commit comments

Comments
 (0)