tangled
alpha
login
or
join now
opencourse.world
/
ocw-server
0
fork
atom
The server for Open Course World
0
fork
atom
overview
issues
pulls
pipelines
dyna: add queries for leaderboard searches
mm2srv
3 years ago
36e289fb
24800161
+89
-12
6 changed files
expand all
collapse all
unified
split
db
dyna
dyna.go
search_users.go
migrations
000004_user_searches.down.sql
000004_user_searches.up.sql
nex
datastore
datastore_smm2.go
proto
datastore_smm2.proto
+2
-1
db/dyna/dyna.go
reviewed
···
748
748
749
749
func (s *DB) IdsFromPgxQuery(rows pgx.Rows) ([]int64, error) {
750
750
// One liner to get list of ids from pgx query
751
751
+
defer rows.Close()
752
752
+
751
753
ids := []int64{}
752
754
for rows.Next() {
753
755
var data_id int64
···
757
759
}
758
760
ids = append(ids, data_id)
759
761
}
760
760
-
rows.Close()
761
762
762
763
return ids, nil
763
764
}
+83
-9
db/dyna/search_users.go
reviewed
···
1
1
package dyna
2
2
3
3
import (
4
4
+
"context"
5
5
+
"github.com/jackc/pgx/v4"
6
6
+
"smm2_gameserver/nex/connection/user"
4
7
"smm2_gameserver/nex/datastore"
5
8
)
6
9
10
10
+
func (s *DB) GetUsersAndRanksFromIdRows(pid datastore.Pid, userOption uint32, offset uint32, rows pgx.Rows) ([]datastore.UserInfo, []uint32, bool, error) {
11
11
+
ids, err := s.IdsFromPgxQuery(rows)
12
12
+
if err != nil {
13
13
+
return []datastore.UserInfo{}, []uint32{}, false, err
14
14
+
}
15
15
+
16
16
+
users := []datastore.UserInfo{}
17
17
+
state := &user.State{Pid: uint64(pid)}
18
18
+
for _, pid := range ids {
19
19
+
u, err := s.GetUserInfoByPid(state, datastore.Pid(pid), userOption)
20
20
+
if err != nil {
21
21
+
return []datastore.UserInfo{}, []uint32{}, false, err
22
22
+
}
23
23
+
users = append(users, u)
24
24
+
}
25
25
+
26
26
+
if err != nil {
27
27
+
return []datastore.UserInfo{}, []uint32{}, false, err
28
28
+
}
29
29
+
30
30
+
// this is not real rank but rather list index. same score/rank isn't accounted for
31
31
+
ranks := []uint32{}
32
32
+
for idx, _ := range users {
33
33
+
ranks = append(ranks, offset+uint32(idx+1))
34
34
+
}
35
35
+
36
36
+
return users, ranks, true, nil
37
37
+
}
38
38
+
39
39
+
// Course Makers Weekly
7
40
func (s *DB) SearchUsersTermsRanking(pid datastore.Pid, param datastore.SearchUsersTermsRankingParam) ([]datastore.UserInfo, []uint32, bool, error) {
8
8
-
return []datastore.UserInfo{}, []uint32{}, false, nil
41
41
+
// TODO: select for regions
42
42
+
// this is not really maker stats per last week but maker stats of active users of the last week,
43
43
+
// since we don't have a field maker stats last week
44
44
+
rows, err := s.Conn.Query(context.Background(), "SELECT id FROM user_info WHERE time_registered IS NOT NULL AND last_active > (CURRENT_DATE - INTERVAL '6 days') ORDER BY maker_points DESC LIMIT $1 OFFSET $2", param.Range.Size, param.Range.Offset)
45
45
+
if err != nil {
46
46
+
return []datastore.UserInfo{}, []uint32{}, false, err
47
47
+
}
48
48
+
return s.GetUsersAndRanksFromIdRows(pid, param.Option, param.Range.Offset, rows)
9
49
}
10
50
51
51
+
// Course Makers All Time
11
52
func (s *DB) SearchUsersUserPoint(pid datastore.Pid, param datastore.SearchUsersUserPointParam) ([]datastore.UserInfo, []uint32, bool, error) {
12
12
-
return []datastore.UserInfo{}, []uint32{}, false, nil
53
53
+
// TODO: select for regions
54
54
+
rows, err := s.Conn.Query(context.Background(), "SELECT id FROM user_info WHERE time_registered IS NOT NULL ORDER BY maker_points DESC LIMIT $1 OFFSET $2", param.Range.Size, param.Range.Offset)
55
55
+
if err != nil {
56
56
+
return []datastore.UserInfo{}, []uint32{}, false, err
57
57
+
}
58
58
+
return s.GetUsersAndRanksFromIdRows(pid, param.Option, param.Range.Offset, rows)
13
59
}
14
60
15
61
func (s *DB) SearchUsersClearRanking(pid datastore.Pid, param datastore.SearchUsersClearRankingParam) ([]datastore.UserInfo, []uint32, bool, error) {
16
16
-
return []datastore.UserInfo{}, []uint32{}, false, nil
17
17
-
}
62
62
+
query := ""
63
63
+
switch param.Type {
64
64
+
case 0: // clears
65
65
+
query = "SELECT pid FROM user_stats ORDER BY clears DESC LIMIT $1 OFFSET $2"
66
66
+
case 1: // first clears
67
67
+
query = "SELECT pid FROM user_stats ORDER BY first_clears DESC LIMIT $1 OFFSET $2"
68
68
+
case 2: // world records
69
69
+
query = "SELECT pid FROM user_stats ORDER BY world_records DESC LIMIT $1 OFFSET $2"
70
70
+
}
18
71
19
19
-
func (s *DB) SearchUsersBattleMode(pid datastore.Pid, param datastore.SearchUsersBattleModeParam) ([]datastore.UserInfo, []uint32, bool, error) {
20
20
-
return []datastore.UserInfo{}, []uint32{}, false, nil
72
72
+
// TODO: select for regions
73
73
+
rows, err := s.Conn.Query(context.Background(), query, param.Range.Size, param.Range.Offset)
74
74
+
if err != nil {
75
75
+
return []datastore.UserInfo{}, []uint32{}, false, err
76
76
+
}
77
77
+
return s.GetUsersAndRanksFromIdRows(pid, param.Option, param.Range.Offset, rows)
21
78
}
22
79
23
80
func (s *DB) SearchUsersFolloweeV2(pid datastore.Pid, param datastore.SearchUsersFolloweeV2Param) ([]datastore.UserInfo, []uint32, bool, error) {
24
24
-
return []datastore.UserInfo{}, []uint32{}, false, nil
81
81
+
// TODO: select for regions
82
82
+
rows, err := s.Conn.Query(context.Background(), "SELECT followed_pid FROM player_follow WHERE pid = $1 ORDER BY id DESC LIMIT $2 OFFSET $3", pid, param.Range.Size, param.Range.Offset)
83
83
+
if err != nil {
84
84
+
return []datastore.UserInfo{}, []uint32{}, false, err
85
85
+
}
86
86
+
return s.GetUsersAndRanksFromIdRows(pid, param.Option, param.Range.Offset, rows)
87
87
+
}
88
88
+
89
89
+
// Players By Endless Difficulty
90
90
+
func (s *DB) SearchUsersEndlessMode(pid datastore.Pid, param datastore.SearchUsersEndlessModeParam) ([]datastore.UserInfo, []uint32, bool, error) {
91
91
+
// TODO: select for regions
92
92
+
rows, err := s.Conn.Query(context.Background(), "SELECT pid FROM endless_stats WHERE difficulty = $1 ORDER BY clears DESC LIMIT $2 OFFSET $3", param.Difficulty, param.Range.Size, param.Range.Offset)
93
93
+
if err != nil {
94
94
+
return []datastore.UserInfo{}, []uint32{}, false, err
95
95
+
}
96
96
+
return s.GetUsersAndRanksFromIdRows(pid, param.Option, param.Range.Offset, rows)
25
97
}
26
98
27
27
-
func (s *DB) SearchUsersOfficial(pid datastore.Pid, param datastore.SearchUsersOfficialParam) ([]datastore.UserInfo, []uint32, bool, error) {
99
99
+
// Versus Players (we have none, return empty list)
100
100
+
func (s *DB) SearchUsersBattleMode(pid datastore.Pid, param datastore.SearchUsersBattleModeParam) ([]datastore.UserInfo, []uint32, bool, error) {
28
101
return []datastore.UserInfo{}, []uint32{}, false, nil
29
102
}
30
103
31
31
-
func (s *DB) SearchUsersEndlessMode(pid datastore.Pid, param datastore.SearchUsersEndlessModeParam) ([]datastore.UserInfo, []uint32, bool, error) {
104
104
+
// Official Nintendo Accounts (we have none, return empty list)
105
105
+
func (s *DB) SearchUsersOfficial(pid datastore.Pid, param datastore.SearchUsersOfficialParam) ([]datastore.UserInfo, []uint32, bool, error) {
32
106
return []datastore.UserInfo{}, []uint32{}, false, nil
33
107
}
+1
db/migrations/000004_user_searches.down.sql
reviewed
···
1
1
+
ALTER TABLE IF EXISTS user_info DROP COLUMN maker_points;
+1
db/migrations/000004_user_searches.up.sql
reviewed
···
1
1
+
ALTER TABLE IF EXISTS user_info ADD COLUMN maker_points INTEGER DEFAULT 0;
+1
-1
nex/datastore/datastore_smm2.go
reviewed
···
736
736
737
737
type SearchUsersEndlessModeParam struct {
738
738
DataStructure uint8
739
739
-
Type uint8
739
739
+
Difficulty uint8
740
740
Option uint32
741
741
IncludeRegions []uint8
742
742
Range ResultRange
+1
-1
nex/datastore/proto/datastore_smm2.proto
reviewed
···
326
326
}
327
327
328
328
struct SearchUsersEndlessModeParam {
329
329
-
uint8 type;
329
329
+
uint8 difficulty;
330
330
uint32 option = 0;
331
331
list<uint8> include_regions = [];
332
332
ResultRange range;