From aa93b382722cc34f63666dc56d68b53e86ce5394 Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Fri, 25 Aug 2023 22:58:52 +0300 Subject: feat: better score handling in profiles (#51) Former-commit-id: 9d30f4ad6e9e077259868e7f05fbe7ac1f65229c --- backend/controllers/userController.go | 174 ++++++++++++++++++++++++++++------ 1 file changed, 147 insertions(+), 27 deletions(-) (limited to 'backend/controllers/userController.go') diff --git a/backend/controllers/userController.go b/backend/controllers/userController.go index 960ecb4..84d589a 100644 --- a/backend/controllers/userController.go +++ b/backend/controllers/userController.go @@ -36,13 +36,14 @@ type ProfileRankingsDetails struct { } type ProfileRecords struct { - P2Singleplayer ProfileRecordsDetails `json:"portal2_singleplayer"` - P2Cooperative ProfileRecordsDetails `json:"portal2_cooperative"` + P2Singleplayer []ProfileRecordsDetails `json:"portal2_singleplayer"` + P2Cooperative []ProfileRecordsDetails `json:"portal2_cooperative"` } type ProfileRecordsDetails struct { - MapID int `json:"map_id"` - Scores []ProfileScores `json:"scores"` + MapID int `json:"map_id"` + MapName string `json:"map_name"` + Scores []ProfileScores `json:"scores"` } type ProfileScores struct { @@ -75,22 +76,78 @@ func Profile(c *gin.Context) { c.JSON(http.StatusUnauthorized, models.ErrorResponse("User not logged in.")) return } - // Get user titles - titles := []models.Title{} - sql := `SELECT t.title_name, t.title_color FROM titles t - INNER JOIN user_titles ut ON t.id=ut.title_id WHERE ut.user_id = $1` + // Get user links + links := models.Links{} + sql := `SELECT u.p2sr, u.steam, u.youtube, u.twitch FROM users u WHERE u.steam_id = $1` + err := database.DB.QueryRow(sql, user.(models.User).SteamID).Scan(&links.P2SR, &links.Steam, &links.YouTube, &links.Twitch) + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) + return + } + // TODO: Get rankings (all maps done in one game) + records := ProfileRecords{ + P2Singleplayer: []ProfileRecordsDetails{}, + P2Cooperative: []ProfileRecordsDetails{}, + } + // Get singleplayer records + sql = `SELECT m.game_id, sp.map_id, m."name", sp.score_count, sp.score_time, sp.demo_id, sp.record_date + FROM records_sp sp INNER JOIN maps m ON sp.map_id = m.id WHERE sp.user_id = $1 ORDER BY sp.map_id, sp.score_count, sp.score_time;` rows, err := database.DB.Query(sql, user.(models.User).SteamID) if err != nil { c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) return } for rows.Next() { - var title models.Title - if err := rows.Scan(&title.Name, &title.Color); err != nil { - c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) - return + var mapID int + var mapName string + var gameID int + score := ProfileScores{} + rows.Scan(&gameID, &mapID, &mapName, &score.ScoreCount, &score.ScoreTime, &score.DemoID, &score.Date) + if gameID != 1 { + continue + } + // More than one record in one map + if len(records.P2Singleplayer) != 0 && mapID == records.P2Singleplayer[len(records.P2Singleplayer)-1].MapID { + records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores = append(records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores, score) + continue } - titles = append(titles, title) + // New map + records.P2Singleplayer = append(records.P2Singleplayer, ProfileRecordsDetails{ + MapID: mapID, + MapName: mapName, + Scores: []ProfileScores{}, + }) + records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores = append(records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores, score) + } + // Get multiplayer records + sql = `SELECT m.game_id, mp.map_id, m."name", mp.score_count, mp.score_time, CASE WHEN host_id = $1 THEN mp.host_demo_id WHEN partner_id = $1 THEN mp.partner_demo_id END demo_id, mp.record_date + FROM records_mp mp INNER JOIN maps m ON mp.map_id = m.id WHERE mp.host_id = $1 OR mp.partner_id = $1 ORDER BY mp.map_id, mp.score_count, mp.score_time;` + rows, err = database.DB.Query(sql, user.(models.User).SteamID) + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) + return + } + for rows.Next() { + var mapID int + var mapName string + var gameID int + score := ProfileScores{} + rows.Scan(&gameID, &mapID, &mapName, &score.ScoreCount, &score.ScoreTime, &score.DemoID, &score.Date) + if gameID != 1 { + continue + } + // More than one record in one map + if len(records.P2Cooperative) != 0 && mapID == records.P2Cooperative[len(records.P2Cooperative)-1].MapID { + records.P2Cooperative[len(records.P2Cooperative)-1].Scores = append(records.P2Cooperative[len(records.P2Cooperative)-1].Scores, score) + continue + } + // New map + records.P2Cooperative = append(records.P2Cooperative, ProfileRecordsDetails{ + MapID: mapID, + MapName: mapName, + Scores: []ProfileScores{}, + }) + records.P2Cooperative[len(records.P2Cooperative)-1].Scores = append(records.P2Cooperative[len(records.P2Cooperative)-1].Scores, score) } c.JSON(http.StatusOK, models.Response{ Success: true, @@ -102,12 +159,11 @@ func Profile(c *gin.Context) { AvatarLink: user.(models.User).AvatarLink, CountryCode: user.(models.User).CountryCode, Titles: user.(models.User).Titles, - Links: models.Links{}, + Links: links, Rankings: ProfileRankings{}, - Records: ProfileRecords{}, + Records: records, }, }) - return } // GET User @@ -131,20 +187,20 @@ func FetchUser(c *gin.Context) { } // Check if user exists var user models.User - err := database.DB.QueryRow(`SELECT * FROM users WHERE steam_id = $1`, id).Scan( - &user.SteamID, &user.UserName, &user.AvatarLink, &user.CountryCode, - &user.CreatedAt, &user.UpdatedAt) + links := models.Links{} + sql := `SELECT u.steam_id, u.user_name, u.avatar_link, u.country_code, u.created_at, u.updated_at, u.p2sr, u.steam, u.youtube, u.twitch FROM users u WHERE u.steam_id = $1` + err := database.DB.QueryRow(sql, id).Scan(&user.SteamID, &user.UserName, &user.AvatarLink, &user.CountryCode, &user.CreatedAt, &user.UpdatedAt, &links.P2SR, &links.Steam, &links.YouTube, &links.Twitch) + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) + return + } if user.SteamID == "" { // User does not exist c.JSON(http.StatusNotFound, models.ErrorResponse("User not found.")) return } - if err != nil { - c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) - return - } // Get user titles - sql := `SELECT t.title_name, t.title_color FROM titles t + sql = `SELECT t.title_name, t.title_color FROM titles t INNER JOIN user_titles ut ON t.id=ut.title_id WHERE ut.user_id = $1` rows, err := database.DB.Query(sql, user.SteamID) if err != nil { @@ -159,6 +215,71 @@ func FetchUser(c *gin.Context) { } user.Titles = append(user.Titles, title) } + // TODO: Get rankings (all maps done in one game) + records := ProfileRecords{ + P2Singleplayer: []ProfileRecordsDetails{}, + P2Cooperative: []ProfileRecordsDetails{}, + } + // Get singleplayer records + sql = `SELECT m.game_id, sp.map_id, m."name", sp.score_count, sp.score_time, sp.demo_id, sp.record_date + FROM records_sp sp INNER JOIN maps m ON sp.map_id = m.id WHERE sp.user_id = $1 ORDER BY sp.map_id, sp.score_count, sp.score_time;` + rows, err = database.DB.Query(sql, user.SteamID) + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) + return + } + for rows.Next() { + var mapID int + var mapName string + var gameID int + score := ProfileScores{} + rows.Scan(&gameID, &mapID, &mapName, &score.ScoreCount, &score.ScoreTime, &score.DemoID, &score.Date) + if gameID != 1 { + continue + } + // More than one record in one map + if len(records.P2Singleplayer) != 0 && mapID == records.P2Singleplayer[len(records.P2Singleplayer)-1].MapID { + records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores = append(records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores, score) + continue + } + // New map + records.P2Singleplayer = append(records.P2Singleplayer, ProfileRecordsDetails{ + MapID: mapID, + MapName: mapName, + Scores: []ProfileScores{}, + }) + records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores = append(records.P2Singleplayer[len(records.P2Singleplayer)-1].Scores, score) + } + // Get multiplayer records + sql = `SELECT m.game_id, mp.map_id, m."name", mp.score_count, mp.score_time, CASE WHEN host_id = $1 THEN mp.host_demo_id WHEN partner_id = $1 THEN mp.partner_demo_id END demo_id, mp.record_date + FROM records_mp mp INNER JOIN maps m ON mp.map_id = m.id WHERE mp.host_id = $1 OR mp.partner_id = $1 ORDER BY mp.map_id, mp.score_count, mp.score_time;` + rows, err = database.DB.Query(sql, user.SteamID) + if err != nil { + c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) + return + } + for rows.Next() { + var mapID int + var mapName string + var gameID int + score := ProfileScores{} + rows.Scan(&gameID, &mapID, &mapName, &score.ScoreCount, &score.ScoreTime, &score.DemoID, &score.Date) + if gameID != 1 { + continue + } + // More than one record in one map + if len(records.P2Cooperative) != 0 && mapID == records.P2Cooperative[len(records.P2Cooperative)-1].MapID { + records.P2Cooperative[len(records.P2Cooperative)-1].Scores = append(records.P2Cooperative[len(records.P2Cooperative)-1].Scores, score) + continue + } + // New map + records.P2Cooperative = append(records.P2Cooperative, ProfileRecordsDetails{ + MapID: mapID, + MapName: mapName, + Scores: []ProfileScores{}, + }) + records.P2Cooperative[len(records.P2Cooperative)-1].Scores = append(records.P2Cooperative[len(records.P2Cooperative)-1].Scores, score) + } c.JSON(http.StatusOK, models.Response{ Success: true, Message: "Successfully retrieved user scores.", @@ -169,12 +290,11 @@ func FetchUser(c *gin.Context) { AvatarLink: user.AvatarLink, CountryCode: user.CountryCode, Titles: user.Titles, - Links: models.Links{}, + Links: links, Rankings: ProfileRankings{}, - Records: ProfileRecords{}, + Records: records, }, }) - return } // PUT Profile -- cgit v1.2.3