aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-06-18 17:08:27 +0300
committerArda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>2023-06-18 17:08:27 +0300
commit345fa5d06a47837fca48137163f8a7bdae33cebf (patch)
tree4fc34ecee284610b4c36c30fa11b19095f508c20 /backend
parentfeat: map routes table (#1) (diff)
downloadlphub-345fa5d06a47837fca48137163f8a7bdae33cebf.tar.gz
lphub-345fa5d06a47837fca48137163f8a7bdae33cebf.tar.bz2
lphub-345fa5d06a47837fca48137163f8a7bdae33cebf.zip
feat: improved map summary response (#43)
Diffstat (limited to 'backend')
-rw-r--r--backend/controllers/mapController.go79
-rw-r--r--backend/models/models.go37
-rw-r--r--backend/models/responses.go5
3 files changed, 59 insertions, 62 deletions
diff --git a/backend/controllers/mapController.go b/backend/controllers/mapController.go
index d8783b7..37b8e9b 100644
--- a/backend/controllers/mapController.go
+++ b/backend/controllers/mapController.go
@@ -3,10 +3,8 @@ package controllers
3import ( 3import (
4 "net/http" 4 "net/http"
5 "strconv" 5 "strconv"
6 "time"
7 6
8 "github.com/gin-gonic/gin" 7 "github.com/gin-gonic/gin"
9 "github.com/lib/pq"
10 "github.com/pektezol/leastportals/backend/database" 8 "github.com/pektezol/leastportals/backend/database"
11 "github.com/pektezol/leastportals/backend/models" 9 "github.com/pektezol/leastportals/backend/models"
12) 10)
@@ -17,37 +15,20 @@ import (
17// @Tags maps 15// @Tags maps
18// @Produce json 16// @Produce json
19// @Param id path int true "Map ID" 17// @Param id path int true "Map ID"
20// @Success 200 {object} models.Response{data=models.Map{data=models.MapSummary}} 18// @Success 200 {object} models.Response{data=models.MapSummaryResponse}
21// @Failure 400 {object} models.Response 19// @Failure 400 {object} models.Response
22// @Router /maps/{id}/summary [get] 20// @Router /maps/{id}/summary [get]
23func FetchMapSummary(c *gin.Context) { 21func FetchMapSummary(c *gin.Context) {
24 id := c.Param("id") 22 id := c.Param("id")
25 // Get map data 23 // Get map data
26 var mapData models.Map 24 response := models.MapSummaryResponse{Map: models.Map{}, Summary: models.MapSummary{History: []models.MapHistory{}, Routes: []models.MapRoute{}}}
27 var mapSummaryData models.MapSummary
28 var mapHistoryData []models.MapHistory
29 intID, err := strconv.Atoi(id) 25 intID, err := strconv.Atoi(id)
30 if err != nil { 26 if err != nil {
31 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 27 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
32 return 28 return
33 } 29 }
34 mapData.ID = intID 30 response.Map.ID = intID
35 var routers pq.StringArray 31 sql := `SELECT m.id, g.name, c.name, m.name,
36 sql := `SELECT g.name, c.name, m.name, m.description, m.showcase,
37 (
38 SELECT array_agg(user_name)
39 FROM map_routers
40 WHERE map_id = $1
41 AND score_count = (
42 SELECT score_count
43 FROM map_history
44 WHERE map_id = $1
45 ORDER BY score_count
46 LIMIT 1
47 )
48 GROUP BY map_routers.user_name
49 ORDER BY user_name
50 ),
51 ( 32 (
52 SELECT COALESCE(avg(rating), 0.0) 33 SELECT COALESCE(avg(rating), 0.0)
53 FROM map_ratings 34 FROM map_ratings
@@ -57,44 +38,53 @@ func FetchMapSummary(c *gin.Context) {
57 INNER JOIN games g ON m.game_id = g.id 38 INNER JOIN games g ON m.game_id = g.id
58 INNER JOIN chapters c ON m.chapter_id = c.id 39 INNER JOIN chapters c ON m.chapter_id = c.id
59 WHERE m.id = $1` 40 WHERE m.id = $1`
60 // TODO: CategoryScores 41 err = database.DB.QueryRow(sql, id).Scan(&response.Map.ID, &response.Map.GameName, &response.Map.ChapterName, &response.Map.MapName, &response.Summary.Rating)
61 err = database.DB.QueryRow(sql, id).Scan(&mapData.GameName, &mapData.ChapterName, &mapData.MapName, &mapSummaryData.Description, &mapSummaryData.Showcase, &routers, &mapSummaryData.Rating)
62 if err != nil { 42 if err != nil {
63 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 43 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
64 return 44 return
65 } 45 }
66 var historyNames pq.StringArray 46 sql = `SELECT user_name, score_count, record_date
67 var historyScores pq.Int32Array
68 var historyDates pq.StringArray
69 sql = `SELECT array_agg(user_name), array_agg(score_count), array_agg(record_date)
70 FROM map_history 47 FROM map_history
71 WHERE map_id = $1` 48 WHERE map_id = $1
72 err = database.DB.QueryRow(sql, id).Scan(&historyNames, &historyScores, &historyDates) 49 ORDER BY record_date ASC`
50 rows, err := database.DB.Query(sql, id)
51 if err != nil {
52 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
53 return
54 }
55 for rows.Next() {
56 history := models.MapHistory{}
57 err = rows.Scan(&history.RunnerName, &history.ScoreCount, &history.Date)
58 if err != nil {
59 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
60 return
61 }
62 response.Summary.History = append(response.Summary.History, history)
63 }
64 sql = `SELECT c.id, c.name, mr.score_count, mr.description, mr.showcase
65 FROM map_routes mr
66 INNER JOIN categories c ON mr.category_id = c.id
67 WHERE mr.map_id = $1
68 ORDER BY mr.score_count DESC`
69 rows, err = database.DB.Query(sql, id)
73 if err != nil { 70 if err != nil {
74 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 71 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
75 return 72 return
76 } 73 }
77 for i := 0; i < len(historyNames); i++ { 74 for rows.Next() {
78 var history models.MapHistory 75 route := models.MapRoute{}
79 history.RunnerName = historyNames[i] 76 err = rows.Scan(&route.Category.ID, &route.Category.Name, &route.ScoreCount, &route.Description, &route.Showcase)
80 history.ScoreCount = int(historyScores[i])
81 layout := "2006-01-02 15:04:05"
82 date, err := time.Parse(layout, historyDates[i])
83 if err != nil { 77 if err != nil {
84 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error())) 78 c.JSON(http.StatusBadRequest, models.ErrorResponse(err.Error()))
85 return 79 return
86 } 80 }
87 history.Date = date 81 response.Summary.Routes = append(response.Summary.Routes, route)
88 mapHistoryData = append(mapHistoryData, history)
89 } 82 }
90 mapSummaryData.History = mapHistoryData
91 mapSummaryData.Routers = routers
92 mapData.Data = mapSummaryData
93 // Return response 83 // Return response
94 c.JSON(http.StatusOK, models.Response{ 84 c.JSON(http.StatusOK, models.Response{
95 Success: true, 85 Success: true,
96 Message: "Successfully retrieved map summary.", 86 Message: "Successfully retrieved map summary.",
97 Data: mapData, 87 Data: response,
98 }) 88 })
99} 89}
100 90
@@ -108,6 +98,7 @@ func FetchMapSummary(c *gin.Context) {
108// @Failure 400 {object} models.Response 98// @Failure 400 {object} models.Response
109// @Router /maps/{id}/leaderboards [get] 99// @Router /maps/{id}/leaderboards [get]
110func FetchMapLeaderboards(c *gin.Context) { 100func FetchMapLeaderboards(c *gin.Context) {
101 // TODO: make new response type
111 id := c.Param("id") 102 id := c.Param("id")
112 // Get map data 103 // Get map data
113 var mapData models.Map 104 var mapData models.Map
@@ -205,7 +196,7 @@ func FetchMapLeaderboards(c *gin.Context) {
205 } 196 }
206 mapRecordsData.Records = records 197 mapRecordsData.Records = records
207 } 198 }
208 mapData.Data = mapRecordsData 199 // mapData.Data = mapRecordsData
209 // Return response 200 // Return response
210 c.JSON(http.StatusOK, models.Response{ 201 c.JSON(http.StatusOK, models.Response{
211 Success: true, 202 Success: true,
diff --git a/backend/models/models.go b/backend/models/models.go
index 49a4f82..5c9b8f8 100644
--- a/backend/models/models.go
+++ b/backend/models/models.go
@@ -23,7 +23,6 @@ type Map struct {
23 GameName string `json:"game_name"` 23 GameName string `json:"game_name"`
24 ChapterName string `json:"chapter_name"` 24 ChapterName string `json:"chapter_name"`
25 MapName string `json:"map_name"` 25 MapName string `json:"map_name"`
26 Data any `json:"data"`
27} 26}
28 27
29type MapShort struct { 28type MapShort struct {
@@ -32,23 +31,9 @@ type MapShort struct {
32} 31}
33 32
34type MapSummary struct { 33type MapSummary struct {
35 Description string `json:"description"` 34 Rating float32 `json:"rating"`
36 Showcase string `json:"showcase"` 35 History []MapHistory `json:"history"`
37 CategoryScores MapCategoryScores `json:"category_scores"` 36 Routes []MapRoute `json:"routes"`
38 Rating float32 `json:"rating"`
39 Routers []string `json:"routers"`
40 History []MapHistory `json:"history"`
41}
42
43type MapCategoryScores struct {
44 CM int `json:"cm"`
45 NoSLA int `json:"no_sla"`
46 InboundsSLA int `json:"inbounds_sla"`
47 Any int `json:"any"`
48}
49
50type MapRecords struct {
51 Records any `json:"records"`
52} 37}
53 38
54type MapHistory struct { 39type MapHistory struct {
@@ -57,6 +42,17 @@ type MapHistory struct {
57 Date time.Time `json:"date"` 42 Date time.Time `json:"date"`
58} 43}
59 44
45type MapRoute struct {
46 Category Category `json:"category"`
47 ScoreCount int `json:"score_count"`
48 Description string `json:"description"`
49 Showcase string `json:"showcase"`
50}
51
52type MapRecords struct {
53 Records any `json:"records"`
54}
55
60type UserRanking struct { 56type UserRanking struct {
61 UserID string `json:"user_id"` 57 UserID string `json:"user_id"`
62 UserName string `json:"user_name"` 58 UserName string `json:"user_name"`
@@ -73,6 +69,11 @@ type Chapter struct {
73 Name string `json:"name"` 69 Name string `json:"name"`
74} 70}
75 71
72type Category struct {
73 ID int `json:"id"`
74 Name string `json:"name"`
75}
76
76type RecordSP struct { 77type RecordSP struct {
77 RecordID int `json:"record_id"` 78 RecordID int `json:"record_id"`
78 Placement int `json:"placement"` 79 Placement int `json:"placement"`
diff --git a/backend/models/responses.go b/backend/models/responses.go
index 5a88353..dc554ff 100644
--- a/backend/models/responses.go
+++ b/backend/models/responses.go
@@ -30,6 +30,11 @@ type ScoreResponse struct {
30 Records any `json:"records"` 30 Records any `json:"records"`
31} 31}
32 32
33type MapSummaryResponse struct {
34 Map Map `json:"map"`
35 Summary MapSummary `json:"summary"`
36}
37
33type SearchResponse struct { 38type SearchResponse struct {
34 Players []UserShort `json:"players"` 39 Players []UserShort `json:"players"`
35 Maps []MapShort `json:"maps"` 40 Maps []MapShort `json:"maps"`