package scoresaber import ( "fmt" "strings" "time" ) // Command 表示从 WebSocket 收到的数据结构 type Command struct { CommandName string `json:"commandName"` CommandData CommandData `json:"commandData"` } func (c Command) ToString() string { if c.CommandName != "score" { return "" } strWithRank := "玩家 %s 使用 %s 在 %s 的 %s 难度(星级为%.1f)中获得了 %d 分,排名第 %d,pp 为 %.2f。" strWithoutRank := "玩家 %s 使用 %s 在 %s 的 %s 难度中获得了 %d 分,排名第 %d。" strWithOutDevice := "玩家 %s 在 %s 的 %s 难度(星级为%.1f)中获得了 %d 分,排名第 %d,pp 为 %.2f。" 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 { return fmt.Sprintf(strWithOutDeviceAndRank, c.CommandData.Score.LeaderboardPlayerInfo.Name, c.CommandData.Leaderboard.SongName, hardStr, c.CommandData.Leaderboard.Stars, c.CommandData.Score.ModifiedScore) } } // LeaderboardPlayerInfo 表示玩家的信息 type LeaderboardPlayerInfo struct { ID string `json:"id"` Name string `json:"name"` ProfilePicture string `json:"profilePicture"` Country string `json:"country"` Permissions int `json:"permissions"` Badges *string `json:"badges"` Role *string `json:"role"` } // Score 表示分数的信息 type Score struct { ID int `json:"id"` LeaderboardPlayerInfo LeaderboardPlayerInfo `json:"leaderboardPlayerInfo"` Rank int `json:"rank"` BaseScore int `json:"baseScore"` ModifiedScore int `json:"modifiedScore"` Pp float64 `json:"pp"` Weight float64 `json:"weight"` Modifiers string `json:"modifiers"` Multiplier float64 `json:"multiplier"` BadCuts int `json:"badCuts"` MissedNotes int `json:"missedNotes"` MaxCombo int `json:"maxCombo"` FullCombo bool `json:"fullCombo"` Hmd int `json:"hmd"` TimeSet time.Time `json:"timeSet"` HasReplay bool `json:"hasReplay"` DeviceHmd *string `json:"deviceHmd"` DeviceControllerLeft *string `json:"deviceControllerLeft"` DeviceControllerRight *string `json:"deviceControllerRight"` } // Difficulty 表示关卡难度信息 type Difficulty struct { LeaderboardID int `json:"leaderboardId"` Difficulty int `json:"difficulty"` GameMode string `json:"gameMode"` DifficultyRaw string `json:"difficultyRaw"` } // Leaderboard 表示排行榜的信息 type Leaderboard struct { ID int `json:"id"` SongHash string `json:"songHash"` SongName string `json:"songName"` SongSubName string `json:"songSubName"` SongAuthorName string `json:"songAuthorName"` LevelAuthorName string `json:"levelAuthorName"` Difficulty Difficulty `json:"difficulty"` MaxScore int `json:"maxScore"` CreatedDate time.Time `json:"createdDate"` RankedDate *time.Time `json:"rankedDate"` QualifiedDate *time.Time `json:"qualifiedDate"` LovedDate *time.Time `json:"lovedDate"` Ranked bool `json:"ranked"` Qualified bool `json:"qualified"` Loved bool `json:"loved"` MaxPP float64 `json:"maxPP"` Stars float64 `json:"stars"` Plays int `json:"plays"` DailyPlays int `json:"dailyPlays"` PositiveModifiers bool `json:"positiveModifiers"` PlayerScore *string `json:"playerScore"` CoverImage string `json:"coverImage"` Difficulties interface{} `json:"difficulties"` } // CommandData 表示命令的数据 type CommandData struct { Score Score `json:"score"` 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 存储分数统计信息 type ScoreStats struct { TotalScore int `json:"totalScore" db:"total_score"` TotalRankedScore int `json:"totalRankedScore" db:"total_ranked_score"` AverageRankedAccuracy float64 `json:"averageRankedAccuracy" db:"average_ranked_accuracy"` TotalPlayCount int `json:"totalPlayCount" db:"total_play_count"` RankedPlayCount int `json:"rankedPlayCount" db:"ranked_play_count"` ReplaysWatched int `json:"replaysWatched" db:"replays_watched"` } // PlayerData 存储玩家的完整信息 type PlayerData struct { ID string `json:"id" db:"id"` Name string `json:"name" db:"name"` ProfilePicture string `json:"profilePicture" db:"profile_picture"` Bio *string `json:"bio" db:"bio"` Country string `json:"country" db:"country"` PP float64 `json:"pp" db:"pp"` Rank int `json:"rank" db:"rank"` CountryRank int `json:"countryRank" db:"country_rank"` Role *string `json:"role" db:"role"` Badges []string `json:"badges" db:"badges"` Histories string `json:"histories" db:"histories"` Permissions int `json:"permissions" db:"permissions"` Banned bool `json:"banned" db:"banned"` Inactive bool `json:"inactive" db:"inactive"` ScoreStats ScoreStats `json:"scoreStats" db:"score_stats"` FirstSeen time.Time `json:"firstSeen" db:"first_seen"` } type PlayerDataLite struct { ID string `json:"id" db:"id"` Name string `json:"name" db:"name"` Country string `json:"country" db:"country"` Device string `json:"device" db:"device"` PP float64 `json:"pp" db:"pp"` Rank int `json:"rank" db:"rank"` CountryRank int `json:"countryRank" db:"country_rank"` TotalScore int `json:"totalScore" db:"total_score"` TotalRankedScore int `json:"totalRankedScore" db:"total_ranked_score"` AverageRankedAccuracy float64 `json:"averageRankedAccuracy" db:"average_ranked_accuracy"` TotalPlayCount int `json:"totalPlayCount" db:"total_play_count"` RankedPlayCount int `json:"rankedPlayCount" db:"ranked_play_count"` ReplaysWatched int `json:"replaysWatched" db:"replays_watched"` GeneratedTime time.Time `json:"generatedTime" db:"generated_time"` } func (p PlayerData) ToString() string { formatedStr := "玩家 %s\n" + "区域 %s\n" + "PP %.1f\n" + "全球排名 %d\n" + "区域排名 %d\n" + "总分 %d\n" + "Ranked谱面总分 %d\n" + "平均Ranked谱面准确率 %.2f\n" + "总游玩次数 %d\n" + "Ranked谱面游玩次数 %d\n" + "回放被观看次数 %d" return fmt.Sprintf(formatedStr, p.Name, p.Country, p.PP, p.Rank, p.CountryRank, p.ScoreStats.TotalScore, p.ScoreStats.TotalRankedScore, p.ScoreStats.AverageRankedAccuracy, p.ScoreStats.TotalPlayCount, p.ScoreStats.RankedPlayCount, p.ScoreStats.ReplaysWatched) } func (p PlayerDataLite) ToString() string { formatedStr := "玩家 %s\n" + "区域 %s\n" + "PP %.1f\n" + "全球排名 %d\n" + "区域排名 %d\n" + "总分 %d\n" + "Ranked谱面总分 %d\n" + "平均Ranked谱面准确率 %.2f\n" + "总游玩次数 %d\n" + "Ranked谱面游玩次数 %d\n" + "回放被观看次数 %d" return fmt.Sprintf(formatedStr, p.Name, p.Country, p.PP, p.Rank, p.CountryRank, p.TotalScore, p.TotalRankedScore, p.AverageRankedAccuracy, p.TotalPlayCount, p.RankedPlayCount, p.ReplaysWatched) } func (p PlayerData) LastDiffToString(lastDayQueryData PlayerDataLite) string { formatedStr := "玩家 %s\n" + "区域 %s\n" + "PP %.1f(%+.1f)\n" + "全球排名 %d(%+d)\n" + "区域排名 %d(%+d)\n" + "总分 %d(%+d)\n" + "Ranked谱面总分 %d(%+d)\n" + "平均Ranked谱面准确率 %.2f(%+.2f)\n" + "总游玩次数 %d(%+d)\n" + "Ranked谱面游玩次数 %d(%+d)\n" + "回放被观看次数 %d" return fmt.Sprintf(formatedStr, p.Name, p.Country, p.PP, p.PP-lastDayQueryData.PP, p.Rank, p.Rank-lastDayQueryData.Rank, p.CountryRank, p.CountryRank-lastDayQueryData.CountryRank, p.ScoreStats.TotalScore, p.ScoreStats.TotalScore-lastDayQueryData.TotalScore, p.ScoreStats.TotalRankedScore, p.ScoreStats.TotalRankedScore-lastDayQueryData.TotalRankedScore, p.ScoreStats.AverageRankedAccuracy, p.ScoreStats.AverageRankedAccuracy-lastDayQueryData.AverageRankedAccuracy, p.ScoreStats.TotalPlayCount, p.ScoreStats.TotalPlayCount-lastDayQueryData.TotalPlayCount, p.ScoreStats.RankedPlayCount, p.ScoreStats.RankedPlayCount-lastDayQueryData.RankedPlayCount, p.ScoreStats.ReplaysWatched) }