diff options
| author | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-09-18 12:03:30 +0300 |
|---|---|---|
| committer | Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> | 2023-09-18 12:03:30 +0300 |
| commit | d69a601251ce3a3e785cf9a32233b7d7dd94fea5 (patch) | |
| tree | ad07b32a77ebd3e92b55828e7e3e0a2b2466bfcc /backend | |
| parent | Merge branch 'main' of https://github.com/pektezol/LeastPortalsHub (diff) | |
| download | lphub-d69a601251ce3a3e785cf9a32233b7d7dd94fea5.tar.gz lphub-d69a601251ce3a3e785cf9a32233b7d7dd94fea5.tar.bz2 lphub-d69a601251ce3a3e785cf9a32233b7d7dd94fea5.zip | |
feat: pagination for map leaderboards
Former-commit-id: 0a38362eadcf1c1ecf5ae29d5a58a015abfd54ee
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/handlers/map.go | 63 | ||||
| -rw-r--r-- | backend/models/models.go | 7 |
2 files changed, 57 insertions, 13 deletions
diff --git a/backend/handlers/map.go b/backend/handlers/map.go index 1d9cee8..b3de2e8 100644 --- a/backend/handlers/map.go +++ b/backend/handlers/map.go | |||
| @@ -16,8 +16,9 @@ type MapSummaryResponse struct { | |||
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | type MapLeaderboardsResponse struct { | 18 | type MapLeaderboardsResponse struct { |
| 19 | Map models.Map `json:"map"` | 19 | Map models.Map `json:"map"` |
| 20 | Records any `json:"records"` | 20 | Records any `json:"records"` |
| 21 | Pagination models.Pagination `json:"pagination"` | ||
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | type ChaptersResponse struct { | 24 | type ChaptersResponse struct { |
| @@ -115,17 +116,24 @@ func FetchMapSummary(c *gin.Context) { | |||
| 115 | // @Description Get map leaderboards with specified id. | 116 | // @Description Get map leaderboards with specified id. |
| 116 | // @Tags maps | 117 | // @Tags maps |
| 117 | // @Produce json | 118 | // @Produce json |
| 118 | // @Param id path int true "Map ID" | 119 | // @Param id path int true "Map ID" |
| 119 | // @Success 200 {object} models.Response{data=MapLeaderboardsResponse} | 120 | // @Param page query int false "Page Number (default: 1)" |
| 120 | // @Failure 400 {object} models.Response | 121 | // @Param pageSize query int false "Number of Records Per Page (default: 10)" |
| 122 | // @Success 200 {object} models.Response{data=MapLeaderboardsResponse} | ||
| 123 | // @Failure 400 {object} models.Response | ||
| 121 | // @Router /maps/{id}/leaderboards [get] | 124 | // @Router /maps/{id}/leaderboards [get] |
| 122 | func FetchMapLeaderboards(c *gin.Context) { | 125 | func FetchMapLeaderboards(c *gin.Context) { |
| 123 | // TODO: make new response type | ||
| 124 | id := c.Param("id") | 126 | id := c.Param("id") |
| 125 | // Get map data | 127 | // Get map data |
| 126 | response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil} | 128 | response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil, Pagination: models.Pagination{}} |
| 127 | // var mapData models.Map | 129 | page, err := strconv.Atoi(c.DefaultQuery("page", "1")) |
| 128 | // var mapRecordsData models.MapRecords | 130 | if err != nil || page < 1 { |
| 131 | page = 1 | ||
| 132 | } | ||
| 133 | pageSize, err := strconv.Atoi(c.DefaultQuery("pageSize", "10")) | ||
| 134 | if err != nil || pageSize < 1 { | ||
| 135 | pageSize = 10 | ||
| 136 | } | ||
| 129 | var isDisabled bool | 137 | var isDisabled bool |
| 130 | intID, err := strconv.Atoi(id) | 138 | intID, err := strconv.Atoi(id) |
| 131 | if err != nil { | 139 | if err != nil { |
| @@ -147,7 +155,8 @@ func FetchMapLeaderboards(c *gin.Context) { | |||
| 147 | c.JSON(http.StatusBadRequest, models.ErrorResponse("Map is not available for competitive boards.")) | 155 | c.JSON(http.StatusBadRequest, models.ErrorResponse("Map is not available for competitive boards.")) |
| 148 | return | 156 | return |
| 149 | } | 157 | } |
| 150 | // TODO: avatar and names for host & partner | 158 | totalRecords := 0 |
| 159 | totalPages := 0 | ||
| 151 | if response.Map.GameName == "Portal 2 - Cooperative" { | 160 | if response.Map.GameName == "Portal 2 - Cooperative" { |
| 152 | records := []RecordMultiplayer{} | 161 | records := []RecordMultiplayer{} |
| 153 | sql = `SELECT | 162 | sql = `SELECT |
| @@ -179,7 +188,7 @@ func FetchMapLeaderboards(c *gin.Context) { | |||
| 179 | ) sub | 188 | ) sub |
| 180 | JOIN users AS host ON sub.host_id = host.steam_id | 189 | JOIN users AS host ON sub.host_id = host.steam_id |
| 181 | JOIN users AS partner ON sub.partner_id = partner.steam_id | 190 | JOIN users AS partner ON sub.partner_id = partner.steam_id |
| 182 | WHERE sub.rn = 1;` | 191 | WHERE sub.rn = 1` |
| 183 | rows, err := database.DB.Query(sql, id) | 192 | rows, err := database.DB.Query(sql, id) |
| 184 | if err != nil { | 193 | if err != nil { |
| 185 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) | 194 | c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) |
| @@ -203,7 +212,18 @@ func FetchMapLeaderboards(c *gin.Context) { | |||
| 203 | records = append(records, record) | 212 | records = append(records, record) |
| 204 | placement++ | 213 | placement++ |
| 205 | } | 214 | } |
| 206 | response.Records = records | 215 | totalRecords = len(records) |
| 216 | totalPages = (totalRecords + pageSize - 1) / pageSize | ||
| 217 | if page > totalPages { | ||
| 218 | c.JSON(http.StatusBadRequest, models.ErrorResponse("Invalid page number.")) | ||
| 219 | return | ||
| 220 | } | ||
| 221 | startIndex := (page - 1) * pageSize | ||
| 222 | endIndex := startIndex + pageSize | ||
| 223 | if endIndex > totalRecords { | ||
| 224 | endIndex = totalRecords | ||
| 225 | } | ||
| 226 | response.Records = records[startIndex:endIndex] | ||
| 207 | } else { | 227 | } else { |
| 208 | records := []RecordSingleplayer{} | 228 | records := []RecordSingleplayer{} |
| 209 | sql = `SELECT id, user_id, users.user_name, users.avatar_link, score_count, score_time, demo_id, record_date | 229 | sql = `SELECT id, user_id, users.user_name, users.avatar_link, score_count, score_time, demo_id, record_date |
| @@ -238,7 +258,24 @@ func FetchMapLeaderboards(c *gin.Context) { | |||
| 238 | records = append(records, record) | 258 | records = append(records, record) |
| 239 | placement++ | 259 | placement++ |
| 240 | } | 260 | } |
| 241 | response.Records = records | 261 | totalRecords = len(records) |
| 262 | totalPages = (totalRecords + pageSize - 1) / pageSize | ||
| 263 | if page > totalPages { | ||
| 264 | c.JSON(http.StatusBadRequest, models.ErrorResponse("Invalid page number.")) | ||
| 265 | return | ||
| 266 | } | ||
| 267 | startIndex := (page - 1) * pageSize | ||
| 268 | endIndex := startIndex + pageSize | ||
| 269 | if endIndex > totalRecords { | ||
| 270 | endIndex = totalRecords | ||
| 271 | } | ||
| 272 | response.Records = records[startIndex:endIndex] | ||
| 273 | } | ||
| 274 | response.Pagination = models.Pagination{ | ||
| 275 | TotalRecords: totalRecords, | ||
| 276 | TotalPages: totalPages, | ||
| 277 | CurrentPage: page, | ||
| 278 | PageSize: pageSize, | ||
| 242 | } | 279 | } |
| 243 | c.JSON(http.StatusOK, models.Response{ | 280 | c.JSON(http.StatusOK, models.Response{ |
| 244 | Success: true, | 281 | Success: true, |
diff --git a/backend/models/models.go b/backend/models/models.go index 2d54295..35929c1 100644 --- a/backend/models/models.go +++ b/backend/models/models.go | |||
| @@ -109,6 +109,13 @@ type Links struct { | |||
| 109 | Twitch string `json:"twitch"` | 109 | Twitch string `json:"twitch"` |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | type Pagination struct { | ||
| 113 | TotalRecords int `json:"total_records"` | ||
| 114 | TotalPages int `json:"total_pages"` | ||
| 115 | CurrentPage int `json:"current_page"` | ||
| 116 | PageSize int `json:"page_size"` | ||
| 117 | } | ||
| 118 | |||
| 112 | type PlayerSummaries struct { | 119 | type PlayerSummaries struct { |
| 113 | SteamId string `json:"steamid"` | 120 | SteamId string `json:"steamid"` |
| 114 | CommunityVisibilityState int `json:"communityvisibilitystate"` | 121 | CommunityVisibilityState int `json:"communityvisibilitystate"` |