aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-08-30 16:31:29 +0300
committerArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-08-30 16:31:29 +0300
commitee533d9405e3ffe1fd1a073e29f839568c465ba7 (patch)
tree3545800d74f99fe5055f3b81bd83536bdcc94bc9
parentrefactor: reorganizing packages (diff)
downloadlphub-ee533d9405e3ffe1fd1a073e29f839568c465ba7.tar.gz
lphub-ee533d9405e3ffe1fd1a073e29f839568c465ba7.tar.bz2
lphub-ee533d9405e3ffe1fd1a073e29f839568c465ba7.zip
feat: better leaderboards response, coop additions (#45)
Former-commit-id: 3a4a8af14d054512204b5ca4c25a6603ec94773e
-rw-r--r--backend/handlers/map.go104
-rw-r--r--backend/models/models.go28
2 files changed, 79 insertions, 53 deletions
diff --git a/backend/handlers/map.go b/backend/handlers/map.go
index b47e793..9b0caef 100644
--- a/backend/handlers/map.go
+++ b/backend/handlers/map.go
@@ -3,6 +3,7 @@ package handlers
3import ( 3import (
4 "net/http" 4 "net/http"
5 "strconv" 5 "strconv"
6 "time"
6 7
7 "github.com/gin-gonic/gin" 8 "github.com/gin-gonic/gin"
8 "github.com/pektezol/leastportalshub/backend/database" 9 "github.com/pektezol/leastportalshub/backend/database"
@@ -14,6 +15,11 @@ type MapSummaryResponse struct {
14 Summary models.MapSummary `json:"summary"` 15 Summary models.MapSummary `json:"summary"`
15} 16}
16 17
18type MapLeaderboardsResponse struct {
19 Map models.Map `json:"map"`
20 Records any `json:"records"`
21}
22
17type ChaptersResponse struct { 23type ChaptersResponse struct {
18 Game models.Game `json:"game"` 24 Game models.Game `json:"game"`
19 Chapters []models.Chapter `json:"chapters"` 25 Chapters []models.Chapter `json:"chapters"`
@@ -24,6 +30,34 @@ type ChapterMapsResponse struct {
24 Maps []models.MapShort `json:"maps"` 30 Maps []models.MapShort `json:"maps"`
25} 31}
26 32
33type RecordSingleplayer struct {
34 Placement int `json:"placement"`
35 RecordID int `json:"record_id"`
36 ScoreCount int `json:"score_count"`
37 ScoreTime int `json:"score_time"`
38 UserID string `json:"user_id"`
39 UserName string `json:"user_name"`
40 UserAvatar string `json:"user_avatar"`
41 DemoID string `json:"demo_id"`
42 RecordDate time.Time `json:"record_date"`
43}
44
45type RecordMultiplayer struct {
46 Placement int `json:"placement"`
47 RecordID int `json:"record_id"`
48 ScoreCount int `json:"score_count"`
49 ScoreTime int `json:"score_time"`
50 HostID string `json:"host_id"`
51 HostName string `json:"host_name"`
52 HostAvatar string `json:"host_avatar"`
53 PartnerID string `json:"partner_id"`
54 PartnerName string `json:"partner_name"`
55 PartnerAvatar string `json:"partner_avatar"`
56 HostDemoID string `json:"host_demo_id"`
57 PartnerDemoID string `json:"partner_demo_id"`
58 RecordDate time.Time `json:"record_date"`
59}
60
27// GET Map Summary 61// GET Map Summary
28// 62//
29// @Description Get map summary with specified id. 63// @Description Get map summary with specified id.
@@ -88,28 +122,29 @@ func FetchMapSummary(c *gin.Context) {
88// @Tags maps 122// @Tags maps
89// @Produce json 123// @Produce json
90// @Param id path int true "Map ID" 124// @Param id path int true "Map ID"
91// @Success 200 {object} models.Response{data=models.Map{data=models.MapRecords}} 125// @Success 200 {object} models.Response{data=MapLeaderboardsResponse}
92// @Failure 400 {object} models.Response 126// @Failure 400 {object} models.Response
93// @Router /maps/{id}/leaderboards [get] 127// @Router /maps/{id}/leaderboards [get]
94func FetchMapLeaderboards(c *gin.Context) { 128func FetchMapLeaderboards(c *gin.Context) {
95 // TODO: make new response type 129 // TODO: make new response type
96 id := c.Param("id") 130 id := c.Param("id")
97 // Get map data 131 // Get map data
98 var mapData models.Map 132 response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil}
99 var mapRecordsData models.MapRecords 133 // var mapData models.Map
134 // var mapRecordsData models.MapRecords
100 var isDisabled bool 135 var isDisabled bool
101 intID, err := strconv.Atoi(id) 136 intID, err := strconv.Atoi(id)
102 if err != nil { 137 if err != nil {
103 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 138 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
104 return 139 return
105 } 140 }
106 mapData.ID = intID 141 response.Map.ID = intID
107 sql := `SELECT g.name, c.name, m.name, is_disabled, m.image 142 sql := `SELECT g.name, c.name, m.name, is_disabled, m.image
108 FROM maps m 143 FROM maps m
109 INNER JOIN games g ON m.game_id = g.id 144 INNER JOIN games g ON m.game_id = g.id
110 INNER JOIN chapters c ON m.chapter_id = c.id 145 INNER JOIN chapters c ON m.chapter_id = c.id
111 WHERE m.id = $1` 146 WHERE m.id = $1`
112 err = database.DB.QueryRow(sql, id).Scan(&mapData.GameName, &mapData.ChapterName, &mapData.MapName, &isDisabled, &mapData.Image) 147 err = database.DB.QueryRow(sql, id).Scan(&response.Map.GameName, &response.Map.ChapterName, &response.Map.MapName, &isDisabled, &response.Map.Image)
113 if err != nil { 148 if err != nil {
114 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 149 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
115 return 150 return
@@ -119,17 +154,38 @@ func FetchMapLeaderboards(c *gin.Context) {
119 return 154 return
120 } 155 }
121 // TODO: avatar and names for host & partner 156 // TODO: avatar and names for host & partner
122 // Get records from the map 157 if response.Map.GameName == "Portal 2 - Cooperative" {
123 if mapData.GameName == "Portal 2 - Cooperative" { 158 records := []RecordMultiplayer{}
124 var records []models.RecordMP 159 sql = `SELECT
125 sql = `SELECT id, host_id, partner_id, score_count, score_time, host_demo_id, partner_demo_id, record_date 160 sub.id,
126 FROM ( 161 sub.host_id,
127 SELECT id, host_id, partner_id, score_count, score_time, host_demo_id, partner_demo_id, record_date, 162 host.user_name AS host_user_name,
128 ROW_NUMBER() OVER (PARTITION BY host_id, partner_id ORDER BY score_count, score_time) AS rn 163 host.avatar_link AS host_avatar_link,
129 FROM records_mp 164 sub.partner_id,
130 WHERE map_id = $1 165 partner.user_name AS partner_user_name,
131 ) sub 166 partner.avatar_link AS partner_avatar_link,
132 WHERE rn = 1` 167 sub.score_count,
168 sub.score_time,
169 sub.host_demo_id,
170 sub.partner_demo_id,
171 sub.record_date
172 FROM (
173 SELECT
174 id,
175 host_id,
176 partner_id,
177 score_count,
178 score_time,
179 host_demo_id,
180 partner_demo_id,
181 record_date,
182 ROW_NUMBER() OVER (PARTITION BY host_id, partner_id ORDER BY score_count, score_time) AS rn
183 FROM records_mp
184 WHERE map_id = $1
185 ) sub
186 JOIN users AS host ON sub.host_id = host.steam_id
187 JOIN users AS partner ON sub.partner_id = partner.steam_id
188 WHERE sub.rn = 1;`
133 rows, err := database.DB.Query(sql, id) 189 rows, err := database.DB.Query(sql, id)
134 if err != nil { 190 if err != nil {
135 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 191 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
@@ -138,8 +194,8 @@ func FetchMapLeaderboards(c *gin.Context) {
138 placement := 1 194 placement := 1
139 ties := 0 195 ties := 0
140 for rows.Next() { 196 for rows.Next() {
141 var record models.RecordMP 197 var record RecordMultiplayer
142 err := rows.Scan(&record.RecordID, &record.HostID, &record.PartnerID, &record.ScoreCount, &record.ScoreTime, &record.HostDemoID, &record.PartnerDemoID, &record.RecordDate) 198 err := rows.Scan(&record.RecordID, &record.HostID, &record.HostName, &record.HostAvatar, &record.PartnerID, &record.PartnerName, &record.PartnerAvatar, &record.ScoreCount, &record.ScoreTime, &record.HostDemoID, &record.PartnerDemoID, &record.RecordDate)
143 if err != nil { 199 if err != nil {
144 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 200 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
145 return 201 return
@@ -153,9 +209,9 @@ func FetchMapLeaderboards(c *gin.Context) {
153 records = append(records, record) 209 records = append(records, record)
154 placement++ 210 placement++
155 } 211 }
156 mapRecordsData.Records = records 212 response.Records = records
157 } else { 213 } else {
158 var records []models.RecordSP 214 records := []RecordSingleplayer{}
159 sql = `SELECT id, user_id, users.user_name, users.avatar_link, score_count, score_time, demo_id, record_date 215 sql = `SELECT id, user_id, users.user_name, users.avatar_link, score_count, score_time, demo_id, record_date
160 FROM ( 216 FROM (
161 SELECT id, user_id, score_count, score_time, demo_id, record_date, 217 SELECT id, user_id, score_count, score_time, demo_id, record_date,
@@ -173,7 +229,7 @@ func FetchMapLeaderboards(c *gin.Context) {
173 placement := 1 229 placement := 1
174 ties := 0 230 ties := 0
175 for rows.Next() { 231 for rows.Next() {
176 var record models.RecordSP 232 var record RecordSingleplayer
177 err := rows.Scan(&record.RecordID, &record.UserID, &record.UserName, &record.UserAvatar, &record.ScoreCount, &record.ScoreTime, &record.DemoID, &record.RecordDate) 233 err := rows.Scan(&record.RecordID, &record.UserID, &record.UserName, &record.UserAvatar, &record.ScoreCount, &record.ScoreTime, &record.DemoID, &record.RecordDate)
178 if err != nil { 234 if err != nil {
179 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 235 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
@@ -188,14 +244,12 @@ func FetchMapLeaderboards(c *gin.Context) {
188 records = append(records, record) 244 records = append(records, record)
189 placement++ 245 placement++
190 } 246 }
191 mapRecordsData.Records = records 247 response.Records = records
192 } 248 }
193 // mapData.Data = mapRecordsData
194 // Return response
195 c.JSON(http.StatusOK, models.Response{ 249 c.JSON(http.StatusOK, models.Response{
196 Success: true, 250 Success: true,
197 Message: "Successfully retrieved map leaderboards.", 251 Message: "Successfully retrieved map leaderboards.",
198 Data: mapData, 252 Data: response,
199 }) 253 })
200} 254}
201 255
diff --git a/backend/models/models.go b/backend/models/models.go
index f124db5..b706d25 100644
--- a/backend/models/models.go
+++ b/backend/models/models.go
@@ -104,34 +104,6 @@ type Links struct {
104 Twitch string `json:"twitch"` 104 Twitch string `json:"twitch"`
105} 105}
106 106
107type RecordSP struct {
108 RecordID int `json:"record_id"`
109 Placement int `json:"placement"`
110 UserID string `json:"user_id"`
111 UserName string `json:"user_name"`
112 UserAvatar string `json:"user_avatar"`
113 ScoreCount int `json:"score_count"`
114 ScoreTime int `json:"score_time"`
115 DemoID string `json:"demo_id"`
116 RecordDate time.Time `json:"record_date"`
117}
118
119type RecordMP struct {
120 RecordID int `json:"record_id"`
121 Placement int `json:"placement"`
122 HostID string `json:"host_id"`
123 HostName string `json:"host_name"`
124 HostAvatar string `json:"host_avatar"`
125 PartnerID string `json:"partner_id"`
126 PartnerName string `json:"partner_name"`
127 PartnerAvatar string `json:"partner_avatar"`
128 ScoreCount int `json:"score_count"`
129 ScoreTime int `json:"score_time"`
130 HostDemoID string `json:"host_demo_id"`
131 PartnerDemoID string `json:"partner_demo_id"`
132 RecordDate time.Time `json:"record_date"`
133}
134
135type PlayerSummaries struct { 107type PlayerSummaries struct {
136 SteamId string `json:"steamid"` 108 SteamId string `json:"steamid"`
137 CommunityVisibilityState int `json:"communityvisibilitystate"` 109 CommunityVisibilityState int `json:"communityvisibilitystate"`