aboutsummaryrefslogtreecommitdiff
path: root/backend/handlers/map.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--backend/handlers/map.go (renamed from backend/controllers/mapController.go)131
1 files changed, 97 insertions, 34 deletions
diff --git a/backend/controllers/mapController.go b/backend/handlers/map.go
index ebd65dd..1d9cee8 100644
--- a/backend/controllers/mapController.go
+++ b/backend/handlers/map.go
@@ -1,26 +1,69 @@
1package controllers 1package handlers
2 2
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"
9 "github.com/pektezol/leastportalshub/backend/models" 10 "github.com/pektezol/leastportalshub/backend/models"
10) 11)
11 12
13type MapSummaryResponse struct {
14 Map models.Map `json:"map"`
15 Summary models.MapSummary `json:"summary"`
16}
17
18type MapLeaderboardsResponse struct {
19 Map models.Map `json:"map"`
20 Records any `json:"records"`
21}
22
23type ChaptersResponse struct {
24 Game models.Game `json:"game"`
25 Chapters []models.Chapter `json:"chapters"`
26}
27
28type ChapterMapsResponse struct {
29 Chapter models.Chapter `json:"chapter"`
30 Maps []models.MapShort `json:"maps"`
31}
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 User models.UserShortWithAvatar `json:"user"`
39 DemoID string `json:"demo_id"`
40 RecordDate time.Time `json:"record_date"`
41}
42
43type RecordMultiplayer struct {
44 Placement int `json:"placement"`
45 RecordID int `json:"record_id"`
46 ScoreCount int `json:"score_count"`
47 ScoreTime int `json:"score_time"`
48 Host models.UserShortWithAvatar `json:"host"`
49 Partner models.UserShortWithAvatar `json:"partner"`
50 HostDemoID string `json:"host_demo_id"`
51 PartnerDemoID string `json:"partner_demo_id"`
52 RecordDate time.Time `json:"record_date"`
53}
54
12// GET Map Summary 55// GET Map Summary
13// 56//
14// @Description Get map summary with specified id. 57// @Description Get map summary with specified id.
15// @Tags maps 58// @Tags maps
16// @Produce json 59// @Produce json
17// @Param id path int true "Map ID" 60// @Param id path int true "Map ID"
18// @Success 200 {object} models.Response{data=models.MapSummaryResponse} 61// @Success 200 {object} models.Response{data=MapSummaryResponse}
19// @Failure 400 {object} models.Response 62// @Failure 400 {object} models.Response
20// @Router /maps/{id}/summary [get] 63// @Router /maps/{id}/summary [get]
21func FetchMapSummary(c *gin.Context) { 64func FetchMapSummary(c *gin.Context) {
22 id := c.Param("id") 65 id := c.Param("id")
23 response := models.MapSummaryResponse{Map: models.Map{}, Summary: models.MapSummary{Routes: []models.MapRoute{}}} 66 response := MapSummaryResponse{Map: models.Map{}, Summary: models.MapSummary{Routes: []models.MapRoute{}}}
24 intID, err := strconv.Atoi(id) 67 intID, err := strconv.Atoi(id)
25 if err != nil { 68 if err != nil {
26 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 69 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
@@ -73,28 +116,29 @@ func FetchMapSummary(c *gin.Context) {
73// @Tags maps 116// @Tags maps
74// @Produce json 117// @Produce json
75// @Param id path int true "Map ID" 118// @Param id path int true "Map ID"
76// @Success 200 {object} models.Response{data=models.Map{data=models.MapRecords}} 119// @Success 200 {object} models.Response{data=MapLeaderboardsResponse}
77// @Failure 400 {object} models.Response 120// @Failure 400 {object} models.Response
78// @Router /maps/{id}/leaderboards [get] 121// @Router /maps/{id}/leaderboards [get]
79func FetchMapLeaderboards(c *gin.Context) { 122func FetchMapLeaderboards(c *gin.Context) {
80 // TODO: make new response type 123 // TODO: make new response type
81 id := c.Param("id") 124 id := c.Param("id")
82 // Get map data 125 // Get map data
83 var mapData models.Map 126 response := MapLeaderboardsResponse{Map: models.Map{}, Records: nil}
84 var mapRecordsData models.MapRecords 127 // var mapData models.Map
128 // var mapRecordsData models.MapRecords
85 var isDisabled bool 129 var isDisabled bool
86 intID, err := strconv.Atoi(id) 130 intID, err := strconv.Atoi(id)
87 if err != nil { 131 if err != nil {
88 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 132 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
89 return 133 return
90 } 134 }
91 mapData.ID = intID 135 response.Map.ID = intID
92 sql := `SELECT g.name, c.name, m.name, is_disabled, m.image 136 sql := `SELECT g.name, c.name, m.name, is_disabled, m.image, g.is_coop
93 FROM maps m 137 FROM maps m
94 INNER JOIN games g ON m.game_id = g.id 138 INNER JOIN games g ON m.game_id = g.id
95 INNER JOIN chapters c ON m.chapter_id = c.id 139 INNER JOIN chapters c ON m.chapter_id = c.id
96 WHERE m.id = $1` 140 WHERE m.id = $1`
97 err = database.DB.QueryRow(sql, id).Scan(&mapData.GameName, &mapData.ChapterName, &mapData.MapName, &isDisabled, &mapData.Image) 141 err = database.DB.QueryRow(sql, id).Scan(&response.Map.GameName, &response.Map.ChapterName, &response.Map.MapName, &isDisabled, &response.Map.Image, &response.Map.IsCoop)
98 if err != nil { 142 if err != nil {
99 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 143 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
100 return 144 return
@@ -104,17 +148,38 @@ func FetchMapLeaderboards(c *gin.Context) {
104 return 148 return
105 } 149 }
106 // TODO: avatar and names for host & partner 150 // TODO: avatar and names for host & partner
107 // Get records from the map 151 if response.Map.GameName == "Portal 2 - Cooperative" {
108 if mapData.GameName == "Portal 2 - Cooperative" { 152 records := []RecordMultiplayer{}
109 var records []models.RecordMP 153 sql = `SELECT
110 sql = `SELECT id, host_id, partner_id, score_count, score_time, host_demo_id, partner_demo_id, record_date 154 sub.id,
111 FROM ( 155 sub.host_id,
112 SELECT id, host_id, partner_id, score_count, score_time, host_demo_id, partner_demo_id, record_date, 156 host.user_name AS host_user_name,
113 ROW_NUMBER() OVER (PARTITION BY host_id, partner_id ORDER BY score_count, score_time) AS rn 157 host.avatar_link AS host_avatar_link,
114 FROM records_mp 158 sub.partner_id,
115 WHERE map_id = $1 159 partner.user_name AS partner_user_name,
116 ) sub 160 partner.avatar_link AS partner_avatar_link,
117 WHERE rn = 1` 161 sub.score_count,
162 sub.score_time,
163 sub.host_demo_id,
164 sub.partner_demo_id,
165 sub.record_date
166 FROM (
167 SELECT
168 id,
169 host_id,
170 partner_id,
171 score_count,
172 score_time,
173 host_demo_id,
174 partner_demo_id,
175 record_date,
176 ROW_NUMBER() OVER (PARTITION BY host_id, partner_id ORDER BY score_count, score_time) AS rn
177 FROM records_mp
178 WHERE map_id = $1
179 ) sub
180 JOIN users AS host ON sub.host_id = host.steam_id
181 JOIN users AS partner ON sub.partner_id = partner.steam_id
182 WHERE sub.rn = 1;`
118 rows, err := database.DB.Query(sql, id) 183 rows, err := database.DB.Query(sql, id)
119 if err != nil { 184 if err != nil {
120 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 185 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
@@ -123,8 +188,8 @@ func FetchMapLeaderboards(c *gin.Context) {
123 placement := 1 188 placement := 1
124 ties := 0 189 ties := 0
125 for rows.Next() { 190 for rows.Next() {
126 var record models.RecordMP 191 var record RecordMultiplayer
127 err := rows.Scan(&record.RecordID, &record.HostID, &record.PartnerID, &record.ScoreCount, &record.ScoreTime, &record.HostDemoID, &record.PartnerDemoID, &record.RecordDate) 192 err := rows.Scan(&record.RecordID, &record.Host.SteamID, &record.Host.UserName, &record.Host.AvatarLink, &record.Partner.SteamID, &record.Partner.UserName, &record.Partner.AvatarLink, &record.ScoreCount, &record.ScoreTime, &record.HostDemoID, &record.PartnerDemoID, &record.RecordDate)
128 if err != nil { 193 if err != nil {
129 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 194 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
130 return 195 return
@@ -138,9 +203,9 @@ func FetchMapLeaderboards(c *gin.Context) {
138 records = append(records, record) 203 records = append(records, record)
139 placement++ 204 placement++
140 } 205 }
141 mapRecordsData.Records = records 206 response.Records = records
142 } else { 207 } else {
143 var records []models.RecordSP 208 records := []RecordSingleplayer{}
144 sql = `SELECT id, user_id, users.user_name, users.avatar_link, score_count, score_time, demo_id, record_date 209 sql = `SELECT id, user_id, users.user_name, users.avatar_link, score_count, score_time, demo_id, record_date
145 FROM ( 210 FROM (
146 SELECT id, user_id, score_count, score_time, demo_id, record_date, 211 SELECT id, user_id, score_count, score_time, demo_id, record_date,
@@ -158,8 +223,8 @@ func FetchMapLeaderboards(c *gin.Context) {
158 placement := 1 223 placement := 1
159 ties := 0 224 ties := 0
160 for rows.Next() { 225 for rows.Next() {
161 var record models.RecordSP 226 var record RecordSingleplayer
162 err := rows.Scan(&record.RecordID, &record.UserID, &record.UserName, &record.UserAvatar, &record.ScoreCount, &record.ScoreTime, &record.DemoID, &record.RecordDate) 227 err := rows.Scan(&record.RecordID, &record.User.SteamID, &record.User.UserName, &record.User.AvatarLink, &record.ScoreCount, &record.ScoreTime, &record.DemoID, &record.RecordDate)
163 if err != nil { 228 if err != nil {
164 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 229 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
165 return 230 return
@@ -173,14 +238,12 @@ func FetchMapLeaderboards(c *gin.Context) {
173 records = append(records, record) 238 records = append(records, record)
174 placement++ 239 placement++
175 } 240 }
176 mapRecordsData.Records = records 241 response.Records = records
177 } 242 }
178 // mapData.Data = mapRecordsData
179 // Return response
180 c.JSON(http.StatusOK, models.Response{ 243 c.JSON(http.StatusOK, models.Response{
181 Success: true, 244 Success: true,
182 Message: "Successfully retrieved map leaderboards.", 245 Message: "Successfully retrieved map leaderboards.",
183 Data: mapData, 246 Data: response,
184 }) 247 })
185} 248}
186 249
@@ -220,7 +283,7 @@ func FetchGames(c *gin.Context) {
220// @Tags games & chapters 283// @Tags games & chapters
221// @Produce json 284// @Produce json
222// @Param id path int true "Game ID" 285// @Param id path int true "Game ID"
223// @Success 200 {object} models.Response{data=models.ChaptersResponse} 286// @Success 200 {object} models.Response{data=ChaptersResponse}
224// @Failure 400 {object} models.Response 287// @Failure 400 {object} models.Response
225// @Router /games/{id} [get] 288// @Router /games/{id} [get]
226func FetchChapters(c *gin.Context) { 289func FetchChapters(c *gin.Context) {
@@ -230,7 +293,7 @@ func FetchChapters(c *gin.Context) {
230 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 293 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
231 return 294 return
232 } 295 }
233 var response models.ChaptersResponse 296 var response ChaptersResponse
234 rows, err := database.DB.Query(`SELECT c.id, c.name, g.name FROM chapters c INNER JOIN games g ON c.game_id = g.id WHERE game_id = $1`, gameID) 297 rows, err := database.DB.Query(`SELECT c.id, c.name, g.name FROM chapters c INNER JOIN games g ON c.game_id = g.id WHERE game_id = $1`, gameID)
235 if err != nil { 298 if err != nil {
236 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 299 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
@@ -262,7 +325,7 @@ func FetchChapters(c *gin.Context) {
262// @Tags games & chapters 325// @Tags games & chapters
263// @Produce json 326// @Produce json
264// @Param id path int true "Chapter ID" 327// @Param id path int true "Chapter ID"
265// @Success 200 {object} models.Response{data=models.ChapterMapsResponse} 328// @Success 200 {object} models.Response{data=ChapterMapsResponse}
266// @Failure 400 {object} models.Response 329// @Failure 400 {object} models.Response
267// @Router /chapters/{id} [get] 330// @Router /chapters/{id} [get]
268func FetchChapterMaps(c *gin.Context) { 331func FetchChapterMaps(c *gin.Context) {
@@ -272,7 +335,7 @@ func FetchChapterMaps(c *gin.Context) {
272 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 335 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
273 return 336 return
274 } 337 }
275 var response models.ChapterMapsResponse 338 var response ChapterMapsResponse
276 rows, err := database.DB.Query(`SELECT m.id, m.name, c.name FROM maps m INNER JOIN chapters c ON m.chapter_id = c.id WHERE chapter_id = $1`, chapterID) 339 rows, err := database.DB.Query(`SELECT m.id, m.name, c.name FROM maps m INNER JOIN chapters c ON m.chapter_id = c.id WHERE chapter_id = $1`, chapterID)
277 if err != nil { 340 if err != nil {
278 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 341 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))