feat: 添加beatleader相关查询

This commit is contained in:
lixiangwuxian
2024-10-20 01:26:14 +08:00
parent 674a5b2579
commit 33d98731d2
10 changed files with 1151 additions and 4 deletions

View File

@@ -0,0 +1,304 @@
package beatleader
import (
"database/sql"
"errors"
"log"
"strconv"
"time"
"git.lxtend.com/qqbot/sqlite3"
_ "github.com/mattn/go-sqlite3"
)
func init() {
createScoreTableSQL := `CREATE TABLE IF NOT EXISTS blData (
id TEXT,
name TEXT,
country TEXT,
pp REAL,
rank INTEGER,
country_rank INTEGER,
total_score INTEGER,
total_ranked_score INTEGER,
average_ranked_accuracy REAL,
total_play_count INTEGER,
ranked_play_count INTEGER,
replays_watched INTEGER,
generated_time TEXT
);`
createRecordTableSQL := `CREATE TABLE IF NOT EXISTS blRecordData (
id INTEGER PRIMARY KEY AUTOINCREMENT,
score_id INT,
bl_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,
rank INT,
max_score INT,
full_combo BOOLEAN,
device_hmd VARCHAR(100),
device_controller_left VARCHAR(100),
device_controller_right VARCHAR(100),
generated_time TEXT
);`
sqlite3.TryCreateTable(createScoreTableSQL)
sqlite3.TryCreateTable(createRecordTableSQL)
}
var BLQuery = &blQuery{}
type blQuery struct {
}
func (bl *blQuery) BindBL(qqId string, blId string) (reply string) {
tx, err := sqlite3.GetTran()
if err != nil {
log.Print(err)
}
defer tx.Rollback()
// blId为数字
if _, isNum := strconv.Atoi(blId); isNum != nil {
return "blId格式错误,应当为一串数字"
}
data, _ := FetchPlayerData(blId)
if data == nil {
return "未找到玩家"
}
//去重
if rows, err := tx.Query("SELECT * FROM ssBind WHERE qqid = ?", qqId); err == nil {
if rows.Next() {
return "您已绑定过bl账号,请先输入\"解绑bl\"解绑"
}
rows.Close()
}
_, err = tx.Exec("INSERT INTO ssBind(qqid, ssid) VALUES(?, ?)", qqId, blId)
if err != nil {
return "绑定失败"
}
err = tx.Commit()
if err != nil {
return "无法提交事务"
}
return "和用户名为 " + data.Name + " 的用户绑定成功,输入\"查bl\"查看个人数据"
}
func (bl *blQuery) UnbindBL(qqId string) (reply string) {
tx, err := sqlite3.GetTran()
if err != nil {
log.Print(err)
}
defer tx.Rollback()
//是否已绑定
if rows, err := tx.Query("SELECT * FROM ssBind WHERE qqid = ?", qqId); err == nil {
if !rows.Next() {
return "您未绑定bl账号输入\"绑定bl [blId]\"绑定"
}
rows.Close()
}
_, err = tx.Exec("DELETE FROM ssBind WHERE qqid = ?", qqId)
if err != nil {
return "解绑失败"
}
err = tx.Commit()
if err != nil {
return "无法提交事务"
}
return "解绑成功,重新绑定请输入\"绑定bl [blId]\""
}
func (bl *blQuery) GetScore(qqId string) (reply string, err error) {
db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
tx, err := db.Beginx()
if err != nil {
log.Print(err)
return "数据库连接失败,请稍后重试", err
}
defer tx.Rollback()
blId, err := getBLID(qqId)
if err != nil {
return err.Error(), nil
}
// 查询玩家数据
data, _ := FetchPlayerData(blId)
if data == nil {
return "查询出错,服务器返回了空数据", errors.New("查询出错,服务器返回了空数据")
}
// 构建 PlayerDataLite 结构体
dataLite := PlayerDataLite{
ID: data.ID,
Name: data.Name,
Country: data.Country,
PP: data.AccPp + data.PassPp + data.TechPp,
Rank: data.Rank,
CountryRank: data.CountryRank,
TotalScore: data.ScoreStats.TotalScore,
TotalRankedScore: data.ScoreStats.TotalRankedScore,
AverageRankedAccuracy: data.ScoreStats.AverageRankedAccuracy,
TotalPlayCount: data.ScoreStats.TotalPlayCount,
RankedPlayCount: data.ScoreStats.RankedPlayCount,
ReplaysWatched: data.ScoreStats.WatchedReplays,
GeneratedTime: time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
}
// 查询最近的玩家数据
var lastDataLite PlayerDataLite
err = tx.Get(&lastDataLite, "SELECT * FROM blData WHERE id = ? ORDER BY generated_time DESC LIMIT 1", dataLite.ID)
if err != nil && err != sql.ErrNoRows {
log.Print(err)
return "查询历史数据时出错", err
}
// 如果有新的数据,则插入
if lastDataLite.TotalPlayCount != dataLite.TotalPlayCount {
_, err = tx.NamedExec(`INSERT INTO blData (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 (: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)`, dataLite)
if err != nil {
log.Print(err)
return "插入新数据时出错", err
}
// 提交事务
err = tx.Commit()
if err != nil {
log.Print(err)
return "SQL事务提交失败请重试", err
}
// 返回差异信息
return data.LastDiffToString(lastDataLite), nil
}
// 如果没有新数据,直接提交事务
err = tx.Commit()
if err != nil {
log.Print(err)
return "SQL事务提交失败请重试", err
}
// 返回当前数据的字符串表示
return data.ToString(), nil
}
func (bl *blQuery) SaveRecord(scoreData ScoreData) {
db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
tx, err := db.Beginx()
if err != nil {
log.Print(err)
return
}
defer tx.Rollback()
// 创建 RecordDataLite 结构体实例
dataLite := RecordDataLite{
ScoreID: scoreData.ID,
BlID: scoreData.Player.ID,
Name: scoreData.Player.Name,
Country: scoreData.Player.Country,
SongName: scoreData.Leaderboard.Song.Name,
SongSubName: scoreData.Leaderboard.Song.SubName,
SongAuthorName: scoreData.Leaderboard.Song.Author,
SongHash: scoreData.Leaderboard.Song.Hash,
CoverImage: scoreData.Leaderboard.Song.CoverImage,
DifficultyRaw: scoreData.Leaderboard.Difficulty.DifficultyName,
Stars: 0,
PP: scoreData.Pp,
Weight: scoreData.Weight,
Modifiers: scoreData.Modifiers,
Multiplier: float64(scoreData.ModifiedScore) / float64(scoreData.BaseScore),
BadCuts: scoreData.BadCuts,
Score: scoreData.ModifiedScore,
Rank: scoreData.Rank,
MaxScore: int(float64(scoreData.ModifiedScore) / scoreData.Accuracy),
MissedNotes: scoreData.MissedNotes,
MaxCombo: scoreData.MaxCombo,
FullCombo: scoreData.FullCombo,
DeviceHmd: GetHMDStr(scoreData.HMD),
DeviceControllerLeft: GetControllerStr(scoreData.Controller),
DeviceControllerRight: GetControllerStr(scoreData.Controller),
GeneratedTime: time.Now().Format("2006-01-02 15:04:05.999999999-07:00"),
}
if scoreData.Leaderboard.Difficulty.Stars != nil {
dataLite.Stars = *scoreData.Leaderboard.Difficulty.Stars
}
// 使用 NamedExec 插入数据
_, err = tx.NamedExec(`INSERT INTO blRecordData
(score_id, bl_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,rank, max_score,
full_combo, device_hmd, device_controller_left, device_controller_right,
generated_time)
VALUES (:score_id, :bl_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,:rank, :max_score, :full_combo, :device_hmd, :device_controller_left,
:device_controller_right, :generated_time)`, dataLite)
if err != nil {
log.Print(err)
return
}
// 提交事务
err = tx.Commit()
if err != nil {
log.Print(err)
}
}
func (bl *blQuery) GetRecentScores(count int, qqId string) ([]RecordDataLite, error) {
db := sqlite3.GetDB() // 假设 sqlite3.GetDB() 返回 *sqlx.DB
tx, err := db.Beginx()
if err != nil {
log.Print(err)
return nil, errors.New("数据库连接失败,请稍后重试")
}
defer tx.Rollback()
// 查询绑定的 blId
blId, err := getBLID(qqId)
if err != nil {
return nil, err
}
// 查询记录
var records []RecordDataLite
err = tx.Select(&records, "SELECT * FROM blRecordData WHERE bl_id = ? ORDER BY generated_time DESC LIMIT ?", blId, count)
if err != nil {
if err == sql.ErrNoRows {
return nil, errors.New("未查询到数据")
}
log.Println("查询数据出错:", err)
return nil, errors.New("查询记录失败")
}
// 提交事务
err = tx.Commit()
if err != nil {
log.Print(err)
return nil, errors.New("提交事务失败")
}
return records, nil
}