ripple-api/app/peppy/beatmap.go

134 lines
3.6 KiB
Go

package peppy
import (
"strconv"
"strings"
"github.com/jmoiron/sqlx"
"github.com/thehowl/go-osuapi"
"github.com/valyala/fasthttp"
"github.com/osuyozora/api/common"
)
// GetBeatmap retrieves general beatmap information.
func GetBeatmap(c *fasthttp.RequestCtx, db *sqlx.DB) {
var whereClauses []string
var params []interface{}
limit := strconv.Itoa(common.InString(1, query(c, "limit"), 500, 500))
// since value is not stored, silently ignore
if query(c, "s") != "" {
whereClauses = append(whereClauses, "beatmaps.beatmapset_id = ?")
params = append(params, query(c, "s"))
}
if query(c, "b") != "" {
whereClauses = append(whereClauses, "beatmaps.beatmap_id = ?")
params = append(params, query(c, "b"))
// b is unique, so change limit to 1
limit = "1"
}
// creator is not stored, silently ignore u and type
if query(c, "m") != "" {
m := genmode(query(c, "m"))
if m == "std" {
// Since STD beatmaps are converted, all of the diffs must be != 0
for _, i := range modes {
whereClauses = append(whereClauses, "beatmaps.difficulty_"+i+" != 0")
}
} else {
whereClauses = append(whereClauses, "beatmaps.difficulty_"+m+" != 0")
if query(c, "a") == "1" {
whereClauses = append(whereClauses, "beatmaps.difficulty_std = 0")
}
}
}
if query(c, "h") != "" {
whereClauses = append(whereClauses, "beatmaps.beatmap_md5 = ?")
params = append(params, query(c, "h"))
}
where := strings.Join(whereClauses, " AND ")
if where != "" {
where = "WHERE " + where
}
rows, err := db.Query(`SELECT
beatmapset_id, beatmap_id, ranked, hit_length,
song_name, beatmap_md5, ar, od, bpm, playcount,
passcount, max_combo, difficulty_std, difficulty_taiko, difficulty_ctb, difficulty_mania,
latest_update
FROM beatmaps `+where+" ORDER BY id DESC LIMIT "+limit,
params...)
if err != nil {
common.Err(c, err)
json(c, 200, defaultResponse)
return
}
var bms []osuapi.Beatmap
for rows.Next() {
var (
bm osuapi.Beatmap
rawRankedStatus int
rawName string
rawLastUpdate common.UnixTimestamp
diffs [4]float64
)
err := rows.Scan(
&bm.BeatmapSetID, &bm.BeatmapID, &rawRankedStatus, &bm.HitLength,
&rawName, &bm.FileMD5, &bm.ApproachRate, &bm.OverallDifficulty, &bm.BPM, &bm.Playcount,
&bm.Passcount, &bm.MaxCombo, &diffs[0], &diffs[1], &diffs[2], &diffs[3],
&rawLastUpdate,
)
if err != nil {
common.Err(c, err)
continue
}
bm.TotalLength = bm.HitLength
bm.LastUpdate = osuapi.MySQLDate(rawLastUpdate)
if rawRankedStatus >= 2 {
bm.ApprovedDate = osuapi.MySQLDate(rawLastUpdate)
}
// zero value of ApprovedStatus == osuapi.StatusPending, so /shrug
bm.Approved = rippleToOsuRankedStatus[rawRankedStatus]
bm.Artist, bm.Title, bm.DiffName = parseDiffName(rawName)
for i, diffVal := range diffs {
if diffVal != 0 {
bm.Mode = osuapi.Mode(i)
bm.DifficultyRating = diffVal
break
}
}
bms = append(bms, bm)
}
json(c, 200, bms)
}
var rippleToOsuRankedStatus = map[int]osuapi.ApprovedStatus{
0: osuapi.StatusPending,
1: osuapi.StatusWIP, // it means "needs updating", as the one in the db needs to be updated, but whatever
2: osuapi.StatusRanked,
3: osuapi.StatusApproved,
4: osuapi.StatusQualified,
5: osuapi.StatusLoved,
}
// buggy diffname parser
func parseDiffName(name string) (author string, title string, diffName string) {
parts := strings.SplitN(name, " - ", 2)
author = parts[0]
if len(parts) > 1 {
title = parts[1]
if s := strings.Index(title, " ["); s != -1 {
diffName = title[s+2:]
if len(diffName) != 0 && diffName[len(diffName)-1] == ']' {
diffName = diffName[:len(diffName)-1]
}
title = title[:s]
}
}
return
}