feat: 添加查成绩功能
This commit is contained in:
parent
6fee9f965c
commit
f5e9b74c5a
@ -8,19 +8,17 @@ import (
|
|||||||
"git.lxtend.com/qqbot/service/scoresaber"
|
"git.lxtend.com/qqbot/service/scoresaber"
|
||||||
)
|
)
|
||||||
|
|
||||||
var scoresaberInstance *scoresaber.SSQuery
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
scoresaberInstance = scoresaber.NewSSQuery()
|
|
||||||
handler.RegisterHandler("查ss", getScore)
|
handler.RegisterHandler("查ss", getScore)
|
||||||
handler.RegisterHandler("绑定ss", bindSS)
|
handler.RegisterHandler("绑定ss", bindSS)
|
||||||
handler.RegisterHandler("解绑ss", unbindSS)
|
handler.RegisterHandler("解绑ss", unbindSS)
|
||||||
handler.RegisterHandler("最新ss", getRecentScore)
|
handler.RegisterHandler("最新ss", getMyRecentScore)
|
||||||
|
handler.RegisterHandler("最热ss", getRecentScore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getScore(msg model.Message) (reply model.Reply) {
|
func getScore(msg model.Message) (reply model.Reply) {
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: scoresaberInstance.GetScore(strconv.Itoa(int(msg.UserId))),
|
ReplyMsg: scoresaber.SSQuery.GetScore(strconv.Itoa(int(msg.UserId))),
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
@ -28,7 +26,7 @@ func getScore(msg model.Message) (reply model.Reply) {
|
|||||||
|
|
||||||
func bindSS(msg model.Message) (reply model.Reply) {
|
func bindSS(msg model.Message) (reply model.Reply) {
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: scoresaberInstance.BindSS(strconv.Itoa(int(msg.UserId)), msg.Msg[len("绑定ss "):]),
|
ReplyMsg: scoresaber.SSQuery.BindSS(strconv.Itoa(int(msg.UserId)), msg.Msg[len("绑定ss "):]),
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
@ -36,7 +34,7 @@ func bindSS(msg model.Message) (reply model.Reply) {
|
|||||||
|
|
||||||
func unbindSS(msg model.Message) (reply model.Reply) {
|
func unbindSS(msg model.Message) (reply model.Reply) {
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: scoresaberInstance.UnbindSS(strconv.Itoa(int(msg.UserId))),
|
ReplyMsg: scoresaber.SSQuery.UnbindSS(strconv.Itoa(int(msg.UserId))),
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
@ -44,10 +42,10 @@ func unbindSS(msg model.Message) (reply model.Reply) {
|
|||||||
|
|
||||||
func getRecentScore(msg model.Message) (reply model.Reply) {
|
func getRecentScore(msg model.Message) (reply model.Reply) {
|
||||||
count := 1
|
count := 1
|
||||||
if len(msg.Msg) > len("最新ss ") {
|
if len(msg.Msg) > len("最热ss ") {
|
||||||
var err error
|
var err error
|
||||||
count, err = strconv.Atoi(msg.Msg[len("最新ss "):])
|
count, err = strconv.Atoi(msg.Msg[len("最热ss "):])
|
||||||
if err != nil {
|
if err != nil || count <= 0 {
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: "",
|
ReplyMsg: "",
|
||||||
ReferOriginMsg: true,
|
ReferOriginMsg: true,
|
||||||
@ -57,7 +55,10 @@ func getRecentScore(msg model.Message) (reply model.Reply) {
|
|||||||
}
|
}
|
||||||
scoreMsg := ""
|
scoreMsg := ""
|
||||||
for _, v := range scoresaber.ScoresManager.GetRecentScores(count) {
|
for _, v := range scoresaber.ScoresManager.GetRecentScores(count) {
|
||||||
scoreMsg += v.ToString() + "\n"
|
scoreMsg += v.ToString() + "\n\n"
|
||||||
|
}
|
||||||
|
if len(scoreMsg) > 0 {
|
||||||
|
scoreMsg = scoreMsg[:len(scoreMsg)-len("\n\n")]
|
||||||
}
|
}
|
||||||
return model.Reply{
|
return model.Reply{
|
||||||
ReplyMsg: scoreMsg,
|
ReplyMsg: scoreMsg,
|
||||||
@ -65,3 +66,48 @@ func getRecentScore(msg model.Message) (reply model.Reply) {
|
|||||||
FromMsg: msg,
|
FromMsg: msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getMyRecentScore(msg model.Message) (reply model.Reply) {
|
||||||
|
count := 1
|
||||||
|
scoreMsg := ""
|
||||||
|
if len(msg.Msg) > len("最新ss ") {
|
||||||
|
var err error
|
||||||
|
count, err = strconv.Atoi(msg.Msg[len("最新ss "):])
|
||||||
|
if err != nil || count <= 0 {
|
||||||
|
return model.Reply{
|
||||||
|
ReplyMsg: "",
|
||||||
|
ReferOriginMsg: true,
|
||||||
|
FromMsg: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var userName string
|
||||||
|
recordCount := 0
|
||||||
|
records, err := scoresaber.SSQuery.GetRecentScores(count, strconv.Itoa(int(msg.UserId)))
|
||||||
|
if err != nil {
|
||||||
|
return model.Reply{
|
||||||
|
ReplyMsg: err.Error(),
|
||||||
|
ReferOriginMsg: true,
|
||||||
|
FromMsg: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range records {
|
||||||
|
scoreMsg += v.ToString() + "\n\n"
|
||||||
|
userName = v.Name
|
||||||
|
recordCount++
|
||||||
|
}
|
||||||
|
if len(scoreMsg) > 0 {
|
||||||
|
scoreMsg = scoreMsg[:len(scoreMsg)-len("\n\n")] //去掉最后一个换行符
|
||||||
|
} else {
|
||||||
|
return model.Reply{
|
||||||
|
ReplyMsg: "无最近游戏记录",
|
||||||
|
ReferOriginMsg: true,
|
||||||
|
FromMsg: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model.Reply{
|
||||||
|
ReplyMsg: "玩家 " + userName + " 的" + strconv.Itoa(recordCount) + "条最近记录为:\n" + scoreMsg,
|
||||||
|
ReferOriginMsg: true,
|
||||||
|
FromMsg: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package scoresaber
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@ -38,6 +39,34 @@ func initDB() {
|
|||||||
generated_time TEXT
|
generated_time TEXT
|
||||||
);`
|
);`
|
||||||
|
|
||||||
|
createRecordTableSQL := `CREATE TABLE IF NOT EXISTS ssRecordData (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
score_id INT,
|
||||||
|
ss_id TEXT,
|
||||||
|
name TEXT,
|
||||||
|
country TEXT,
|
||||||
|
song_name VARCHAR(255),
|
||||||
|
song_sub_name VARCHAR(255),
|
||||||
|
song_author_name VARCHAR(255),
|
||||||
|
song_hash VARCHAR(64),
|
||||||
|
cover_image TEXT,
|
||||||
|
difficulty_raw VARCHAR(100),
|
||||||
|
pp REAL,
|
||||||
|
stars REAL,
|
||||||
|
weight REAL,
|
||||||
|
modifiers VARCHAR(255),
|
||||||
|
multiplier REAL,
|
||||||
|
bad_cuts INT,
|
||||||
|
missed_notes INT,
|
||||||
|
max_combo INT,
|
||||||
|
score INT,
|
||||||
|
full_combo BOOLEAN,
|
||||||
|
device_hmd VARCHAR(100),
|
||||||
|
device_controller_left VARCHAR(100),
|
||||||
|
device_controller_right VARCHAR(100),
|
||||||
|
generated_time TEXT
|
||||||
|
);`
|
||||||
|
|
||||||
_, err = db.Exec(createBindTableSQL)
|
_, err = db.Exec(createBindTableSQL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -46,22 +75,28 @@ func initDB() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
_, err = db.Exec(createRecordTableSQL)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SSQuery struct {
|
var SSQuery = &ssQuery{}
|
||||||
|
|
||||||
|
type ssQuery struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSSQuery() *SSQuery {
|
func init() {
|
||||||
initDB()
|
initDB()
|
||||||
db, err := sql.Open("sqlite3", "./bindss.db")
|
db, err := sql.Open("sqlite3", "./bindss.db")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
return &SSQuery{db: db}
|
SSQuery = &ssQuery{db: db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SSQuery) BindSS(qqId string, ssId string) (reply string) {
|
func (ss *ssQuery) BindSS(qqId string, ssId string) (reply string) {
|
||||||
tx, err := ss.db.Begin()
|
tx, err := ss.db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -93,7 +128,7 @@ func (ss *SSQuery) BindSS(qqId string, ssId string) (reply string) {
|
|||||||
return "和用户名为 " + data.Name + " 的用户绑定成功,输入\"查ss\"查看个人数据"
|
return "和用户名为 " + data.Name + " 的用户绑定成功,输入\"查ss\"查看个人数据"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SSQuery) UnbindSS(qqId string) (reply string) {
|
func (ss *ssQuery) UnbindSS(qqId string) (reply string) {
|
||||||
tx, err := ss.db.Begin()
|
tx, err := ss.db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -117,7 +152,7 @@ func (ss *SSQuery) UnbindSS(qqId string) (reply string) {
|
|||||||
return "解绑成功,重新绑定请输入\"绑定ss [ssId]\""
|
return "解绑成功,重新绑定请输入\"绑定ss [ssId]\""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SSQuery) GetScore(qqId string) (reply string) {
|
func (ss *ssQuery) GetScore(qqId string) (reply string) {
|
||||||
tx, err := ss.db.Begin()
|
tx, err := ss.db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -156,13 +191,99 @@ func (ss *SSQuery) GetScore(qqId string) (reply string) {
|
|||||||
tx.Exec("INSERT INTO ssData(id, name, country, pp, rank, country_rank, total_score, total_ranked_score, average_ranked_accuracy, total_play_count, ranked_play_count, replays_watched, generated_time) VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)", dataLite.ID, dataLite.Name, dataLite.Country, dataLite.PP, dataLite.Rank, dataLite.CountryRank, dataLite.TotalScore, dataLite.TotalRankedScore, dataLite.AverageRankedAccuracy, dataLite.TotalPlayCount, dataLite.RankedPlayCount, dataLite.ReplaysWatched, dataLite.GeneratedTime)
|
tx.Exec("INSERT INTO ssData(id, name, country, pp, rank, country_rank, total_score, total_ranked_score, average_ranked_accuracy, total_play_count, ranked_play_count, replays_watched, generated_time) VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)", dataLite.ID, dataLite.Name, dataLite.Country, dataLite.PP, dataLite.Rank, dataLite.CountryRank, dataLite.TotalScore, dataLite.TotalRankedScore, dataLite.AverageRankedAccuracy, dataLite.TotalPlayCount, dataLite.RankedPlayCount, dataLite.ReplaysWatched, dataLite.GeneratedTime)
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "无法提交事务"
|
return "SQL事务提交失败,请重试"
|
||||||
}
|
}
|
||||||
return data.LastDiffToString(lastDataLite)
|
return data.LastDiffToString(lastDataLite)
|
||||||
}
|
}
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "无法提交事务"
|
return "SQL事务提交失败,请重试"
|
||||||
}
|
}
|
||||||
return data.ToString()
|
return data.ToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ss *ssQuery) SaveRecord(cmdData CommandData) {
|
||||||
|
tx, err := ss.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
dataLite := RecordDataLite{
|
||||||
|
ScoreID: cmdData.Score.ID,
|
||||||
|
SsID: cmdData.Score.LeaderboardPlayerInfo.ID,
|
||||||
|
Name: cmdData.Score.LeaderboardPlayerInfo.Name,
|
||||||
|
Country: cmdData.Score.LeaderboardPlayerInfo.Country,
|
||||||
|
SongName: cmdData.Leaderboard.SongName,
|
||||||
|
SongSubName: cmdData.Leaderboard.SongSubName,
|
||||||
|
SongAuthorName: cmdData.Leaderboard.SongAuthorName,
|
||||||
|
SongHash: cmdData.Leaderboard.SongHash,
|
||||||
|
CoverImage: cmdData.Leaderboard.CoverImage,
|
||||||
|
DifficultyRaw: cmdData.Leaderboard.Difficulty.DifficultyRaw,
|
||||||
|
Stars: cmdData.Leaderboard.Stars,
|
||||||
|
PP: cmdData.Score.Pp,
|
||||||
|
Weight: cmdData.Score.Weight,
|
||||||
|
Modifiers: cmdData.Score.Modifiers,
|
||||||
|
Multiplier: cmdData.Score.Multiplier,
|
||||||
|
BadCuts: cmdData.Score.BadCuts,
|
||||||
|
Score: cmdData.Score.ModifiedScore,
|
||||||
|
MissedNotes: cmdData.Score.MissedNotes,
|
||||||
|
MaxCombo: cmdData.Score.MaxCombo,
|
||||||
|
FullCombo: cmdData.Score.FullCombo,
|
||||||
|
DeviceHmd: "",
|
||||||
|
DeviceControllerLeft: "",
|
||||||
|
DeviceControllerRight: "",
|
||||||
|
GeneratedTime: time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
|
||||||
|
}
|
||||||
|
if cmdData.Score.DeviceHmd != nil {
|
||||||
|
dataLite.DeviceHmd = *cmdData.Score.DeviceHmd
|
||||||
|
}
|
||||||
|
if cmdData.Score.DeviceControllerLeft != nil {
|
||||||
|
dataLite.DeviceControllerLeft = *cmdData.Score.DeviceControllerLeft
|
||||||
|
}
|
||||||
|
if cmdData.Score.DeviceControllerRight != nil {
|
||||||
|
dataLite.DeviceControllerRight = *cmdData.Score.DeviceControllerRight
|
||||||
|
}
|
||||||
|
if _, err = tx.Exec("INSERT INTO ssRecordData(score_id, ss_id, name, country, song_name, song_sub_name, song_author_name, song_hash, cover_image, difficulty_raw, pp, stars, weight, modifiers, multiplier, bad_cuts, missed_notes, max_combo,score, full_combo, device_hmd, device_controller_left, device_controller_right, generated_time) VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23,?24)", dataLite.ScoreID, dataLite.SsID, dataLite.Name, dataLite.Country, dataLite.SongName, dataLite.SongSubName, dataLite.SongAuthorName, dataLite.SongHash, dataLite.CoverImage, dataLite.DifficultyRaw, dataLite.PP, dataLite.Stars, dataLite.Weight, dataLite.Modifiers, dataLite.Multiplier, dataLite.BadCuts, dataLite.MissedNotes, dataLite.MaxCombo, dataLite.Score, dataLite.FullCombo, dataLite.DeviceHmd, dataLite.DeviceControllerLeft, dataLite.DeviceControllerRight, dataLite.GeneratedTime); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss *ssQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, error) {
|
||||||
|
tx, err := ss.db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer tx.Rollback()
|
||||||
|
var ssId string
|
||||||
|
tx.QueryRow("SELECT ssid FROM ssBind WHERE qqid = ?", qqId).Scan(&ssId)
|
||||||
|
if ssId == "" {
|
||||||
|
return nil, errors.New("未绑定ss账号,输入\"绑定ss [ssId]\"绑定")
|
||||||
|
}
|
||||||
|
rows, err := tx.Query("SELECT * FROM ssRecordData WHERE ss_id = ? ORDER BY generated_time DESC LIMIT ?", ssId, count)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errors.New("未查询到数据")
|
||||||
|
}
|
||||||
|
log.Println("Query error:", err)
|
||||||
|
return nil, errors.New("")
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var records []RecordDataLite
|
||||||
|
for rows.Next() {
|
||||||
|
var record RecordDataLite
|
||||||
|
if err := rows.Scan(&record.ID, &record.ScoreID, &record.SsID, &record.Name, &record.Country, &record.SongName, &record.SongSubName, &record.SongAuthorName, &record.SongHash, &record.CoverImage, &record.DifficultyRaw, &record.PP, &record.Stars, &record.Weight, &record.Modifiers, &record.Multiplier, &record.BadCuts, &record.MissedNotes, &record.MaxCombo, &record.Score, &record.FullCombo, &record.DeviceHmd, &record.DeviceControllerLeft, &record.DeviceControllerRight, &record.GeneratedTime); err != nil {
|
||||||
|
log.Println("Scan error:", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
records = append(records, record)
|
||||||
|
}
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return records, nil
|
||||||
|
}
|
||||||
|
@ -12,7 +12,6 @@ const wsURL = "wss://scoresaber.com/ws"
|
|||||||
|
|
||||||
var ScoresManager = scoresManager{}
|
var ScoresManager = scoresManager{}
|
||||||
|
|
||||||
// scoresManager 管理最近的 5 条数据
|
|
||||||
type scoresManager struct {
|
type scoresManager struct {
|
||||||
recentScores []Command
|
recentScores []Command
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
@ -34,7 +33,7 @@ func (sm *scoresManager) connect() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sm.retryTimes = 0
|
sm.retryTimes = 0
|
||||||
sm.recentScores = make([]Command, 0, 50)
|
sm.recentScores = make([]Command, 0)
|
||||||
go sm.receiveData()
|
go sm.receiveData()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -49,12 +48,17 @@ func (sm *scoresManager) receiveData() {
|
|||||||
for {
|
for {
|
||||||
var cmd Command
|
var cmd Command
|
||||||
err := sm.conn.ReadJSON(&cmd)
|
err := sm.conn.ReadJSON(&cmd)
|
||||||
if cmd.CommandData.Score.LeaderboardPlayerInfo.Country != "CN" {
|
if err != nil {
|
||||||
log.Printf("非国内玩家数据:%v", cmd)
|
log.Print("读取数据失败:", err)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
sm.retryTimes++
|
||||||
|
if sm.retryTimes > 3 {
|
||||||
|
return
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err != nil {
|
SSQuery.SaveRecord(cmd.CommandData)
|
||||||
log.Printf("读取数据失败:", err)
|
if cmd.CommandData.Score.LeaderboardPlayerInfo.Country != "CN" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sm.mu.Lock()
|
sm.mu.Lock()
|
||||||
@ -67,11 +71,11 @@ func (sm *scoresManager) receiveData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sm *scoresManager) GetRecentScores(count int) []Command {
|
func (sm *scoresManager) GetRecentScores(count int) []Command {
|
||||||
|
sm.mu.Lock()
|
||||||
|
defer sm.mu.Unlock()
|
||||||
if count > len(sm.recentScores) {
|
if count > len(sm.recentScores) {
|
||||||
count = len(sm.recentScores)
|
count = len(sm.recentScores)
|
||||||
}
|
}
|
||||||
sm.mu.Lock()
|
|
||||||
defer sm.mu.Unlock()
|
|
||||||
scoresCopy := make([]Command, count)
|
scoresCopy := make([]Command, count)
|
||||||
copy(scoresCopy, sm.recentScores[len(sm.recentScores)-count:])
|
copy(scoresCopy, sm.recentScores[len(sm.recentScores)-count:])
|
||||||
return scoresCopy
|
return scoresCopy
|
||||||
|
@ -2,6 +2,7 @@ package scoresaber
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,12 +16,19 @@ func (c Command) ToString() string {
|
|||||||
if c.CommandName != "score" {
|
if c.CommandName != "score" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
strWithRank := "玩家 %s 使用 %s 在 %s 的 %s 难度中获得了 %d 分,排名第 %d,pp 为 %.2f。"
|
strWithRank := "玩家 %s 使用 %s 在 %s 的 %s 难度(星级为%.1f)中获得了 %d 分,排名第 %d,pp 为 %.2f。"
|
||||||
strWithoutRank := "玩家 %s 使用 %s 在 %s 的 %s 难度中获得了 %d 分,排名第 %d。"
|
strWithoutRank := "玩家 %s 使用 %s 在 %s 的 %s 难度中获得了 %d 分,排名第 %d。"
|
||||||
if c.CommandData.Leaderboard.Ranked {
|
strWithOutDevice := "玩家 %s 在 %s 的 %s 难度(星级为%.1f)中获得了 %d 分,排名第 %d,pp 为 %.2f。"
|
||||||
return fmt.Sprintf(strWithRank, c.CommandData.Score.LeaderboardPlayerInfo.Name, *c.CommandData.Score.DeviceHmd, c.CommandData.Leaderboard.SongName, c.CommandData.Leaderboard.Difficulty.DifficultyRaw, c.CommandData.Score.ModifiedScore, c.CommandData.Score.Rank, c.CommandData.Score.Pp)
|
strWithOutDeviceAndRank := "玩家 %s 在 %s 的 %s 难度(星级为%.1f)中获得了 %d 分。"
|
||||||
|
hardStr := strings.Split(c.CommandData.Leaderboard.Difficulty.DifficultyRaw, "_")[1]
|
||||||
|
if c.CommandData.Leaderboard.Ranked && c.CommandData.Score.DeviceHmd != nil {
|
||||||
|
return fmt.Sprintf(strWithRank, c.CommandData.Score.LeaderboardPlayerInfo.Name, *c.CommandData.Score.DeviceHmd, c.CommandData.Leaderboard.SongName, hardStr, c.CommandData.Leaderboard.Stars, c.CommandData.Score.ModifiedScore, c.CommandData.Score.Rank, c.CommandData.Score.Pp)
|
||||||
|
} else if !c.CommandData.Leaderboard.Ranked && c.CommandData.Score.DeviceHmd != nil {
|
||||||
|
return fmt.Sprintf(strWithoutRank, c.CommandData.Score.LeaderboardPlayerInfo.Name, *c.CommandData.Score.DeviceHmd, c.CommandData.Leaderboard.SongName, hardStr, c.CommandData.Score.ModifiedScore, c.CommandData.Score.Rank)
|
||||||
|
} else if c.CommandData.Leaderboard.Ranked && c.CommandData.Score.DeviceHmd == nil {
|
||||||
|
return fmt.Sprintf(strWithOutDevice, c.CommandData.Score.LeaderboardPlayerInfo.Name, c.CommandData.Leaderboard.SongName, hardStr, c.CommandData.Leaderboard.Stars, c.CommandData.Score.ModifiedScore, c.CommandData.Score.Rank, c.CommandData.Score.Pp)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf(strWithoutRank, c.CommandData.Score.LeaderboardPlayerInfo.Name, *c.CommandData.Score.DeviceHmd, c.CommandData.Leaderboard.SongName, c.CommandData.Leaderboard.Difficulty.DifficultyRaw, c.CommandData.Score.ModifiedScore, c.CommandData.Score.Rank)
|
return fmt.Sprintf(strWithOutDeviceAndRank, c.CommandData.Score.LeaderboardPlayerInfo.Name, c.CommandData.Leaderboard.SongName, hardStr, c.CommandData.Leaderboard.Stars, c.CommandData.Score.ModifiedScore)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,29 +76,29 @@ type Difficulty struct {
|
|||||||
|
|
||||||
// Leaderboard 表示排行榜的信息
|
// Leaderboard 表示排行榜的信息
|
||||||
type Leaderboard struct {
|
type Leaderboard struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
SongHash string `json:"songHash"`
|
SongHash string `json:"songHash"`
|
||||||
SongName string `json:"songName"`
|
SongName string `json:"songName"`
|
||||||
SongSubName string `json:"songSubName"`
|
SongSubName string `json:"songSubName"`
|
||||||
SongAuthorName string `json:"songAuthorName"`
|
SongAuthorName string `json:"songAuthorName"`
|
||||||
LevelAuthorName string `json:"levelAuthorName"`
|
LevelAuthorName string `json:"levelAuthorName"`
|
||||||
Difficulty Difficulty `json:"difficulty"`
|
Difficulty Difficulty `json:"difficulty"`
|
||||||
MaxScore int `json:"maxScore"`
|
MaxScore int `json:"maxScore"`
|
||||||
CreatedDate time.Time `json:"createdDate"`
|
CreatedDate time.Time `json:"createdDate"`
|
||||||
RankedDate *time.Time `json:"rankedDate"`
|
RankedDate *time.Time `json:"rankedDate"`
|
||||||
QualifiedDate *time.Time `json:"qualifiedDate"`
|
QualifiedDate *time.Time `json:"qualifiedDate"`
|
||||||
LovedDate *time.Time `json:"lovedDate"`
|
LovedDate *time.Time `json:"lovedDate"`
|
||||||
Ranked bool `json:"ranked"`
|
Ranked bool `json:"ranked"`
|
||||||
Qualified bool `json:"qualified"`
|
Qualified bool `json:"qualified"`
|
||||||
Loved bool `json:"loved"`
|
Loved bool `json:"loved"`
|
||||||
MaxPP float64 `json:"maxPP"`
|
MaxPP float64 `json:"maxPP"`
|
||||||
Stars float64 `json:"stars"`
|
Stars float64 `json:"stars"`
|
||||||
Plays int `json:"plays"`
|
Plays int `json:"plays"`
|
||||||
DailyPlays int `json:"dailyPlays"`
|
DailyPlays int `json:"dailyPlays"`
|
||||||
PositiveModifiers bool `json:"positiveModifiers"`
|
PositiveModifiers bool `json:"positiveModifiers"`
|
||||||
PlayerScore *string `json:"playerScore"`
|
PlayerScore *string `json:"playerScore"`
|
||||||
CoverImage string `json:"coverImage"`
|
CoverImage string `json:"coverImage"`
|
||||||
Difficulties *string `json:"difficulties"`
|
Difficulties interface{} `json:"difficulties"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandData 表示命令的数据
|
// CommandData 表示命令的数据
|
||||||
@ -99,6 +107,52 @@ type CommandData struct {
|
|||||||
Leaderboard Leaderboard `json:"leaderboard"`
|
Leaderboard Leaderboard `json:"leaderboard"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 表示记录的数据,本地储存
|
||||||
|
type RecordDataLite struct {
|
||||||
|
ID int `json:"id" db:"id"`
|
||||||
|
ScoreID int `json:"scoreId" db:"score_id"`
|
||||||
|
SsID string `json:"ssId" db:"ss_id"`
|
||||||
|
Name string `json:"name" db:"name"`
|
||||||
|
Country string `json:"country" db:"country"`
|
||||||
|
SongName string `json:"songName" db:"song_name"`
|
||||||
|
SongSubName string `json:"songSubName" db:"song_sub_name"`
|
||||||
|
SongAuthorName string `json:"songAuthorName" db:"song_author_name"`
|
||||||
|
SongHash string `json:"songHash" db:"song_hash"`
|
||||||
|
CoverImage string `json:"coverImage" db:"cover_image"`
|
||||||
|
DifficultyRaw string `json:"difficultyRaw" db:"difficulty_raw"`
|
||||||
|
Stars float64 `json:"stars" db:"stars"`
|
||||||
|
PP float64 `json:"pp" db:"pp"`
|
||||||
|
Weight float64 `json:"weight" db:"weight"`
|
||||||
|
Modifiers string `json:"modifiers" db:"modifiers"`
|
||||||
|
Multiplier float64 `json:"multiplier" db:"multiplier"`
|
||||||
|
BadCuts int `json:"badCuts" db:"bad_cuts"`
|
||||||
|
MissedNotes int `json:"missedNotes" db:"missed_notes"`
|
||||||
|
MaxCombo int `json:"maxCombo" db:"max_combo"`
|
||||||
|
Score int `json:"score" db:"score"`
|
||||||
|
FullCombo bool `json:"fullCombo" db:"full_combo"`
|
||||||
|
DeviceHmd string `json:"deviceHmd" db:"device_hmd"`
|
||||||
|
DeviceControllerLeft string `json:"deviceControllerLeft" db:"device_controller_left"`
|
||||||
|
DeviceControllerRight string `json:"deviceControllerRight" db:"device_controller_right"`
|
||||||
|
GeneratedTime string `json:"generatedTime" db:"generated_time"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r RecordDataLite) ToString() string {
|
||||||
|
formatedStrRanked := "使用 %s 在 %s 的 %s 难度(%.1f星级)中获得了 %d 分,pp 为 %.2f。"
|
||||||
|
formatedStrUnranked := "使用 %s 在 %s 的 %s 难度中获得了 %d 分。"
|
||||||
|
formatedStrWithoutDevice := "在 %s 的 %s 难度(%.1f星级)中获得了 %d 分,pp 为 %.2f。"
|
||||||
|
formatedStrWithoutDeviceAndRank := "在 %s 的 %s 难度(%.1f星级)中获得了 %d 分。"
|
||||||
|
hardStr := strings.Split(r.DifficultyRaw, "_")[1]
|
||||||
|
if r.Stars == 0 && r.DeviceHmd != "" {
|
||||||
|
return fmt.Sprintf(formatedStrUnranked, r.DeviceHmd, r.SongName, hardStr, r.Score)
|
||||||
|
} else if r.Stars != 0 && r.DeviceHmd != "" {
|
||||||
|
return fmt.Sprintf(formatedStrRanked, r.DeviceHmd, r.SongName, hardStr, r.Stars, r.Score, r.PP)
|
||||||
|
} else if r.Stars != 0 && r.DeviceHmd == "" {
|
||||||
|
return fmt.Sprintf(formatedStrWithoutDevice, r.SongName, hardStr, r.Stars, r.Score, r.PP)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf(formatedStrWithoutDeviceAndRank, r.SongName, hardStr, r.Stars, r.Score)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//用户信息
|
//用户信息
|
||||||
|
|
||||||
// ScoreStats 存储分数统计信息
|
// ScoreStats 存储分数统计信息
|
||||||
@ -135,6 +189,7 @@ type PlayerDataLite struct {
|
|||||||
ID string `json:"id" db:"id"`
|
ID string `json:"id" db:"id"`
|
||||||
Name string `json:"name" db:"name"`
|
Name string `json:"name" db:"name"`
|
||||||
Country string `json:"country" db:"country"`
|
Country string `json:"country" db:"country"`
|
||||||
|
Device string `json:"device" db:"device"`
|
||||||
PP float64 `json:"pp" db:"pp"`
|
PP float64 `json:"pp" db:"pp"`
|
||||||
Rank int `json:"rank" db:"rank"`
|
Rank int `json:"rank" db:"rank"`
|
||||||
CountryRank int `json:"countryRank" db:"country_rank"`
|
CountryRank int `json:"countryRank" db:"country_rank"`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user