mkw_rr api tweaks

This commit is contained in:
Blazico 2026-03-28 15:16:05 +01:00
parent 2302f38f94
commit cb506eb9ee
4 changed files with 154 additions and 59 deletions

View File

@ -9,7 +9,7 @@ import (
)
type RaceResultInfo struct {
Players map[string]qr2.PlayerInfo `json:"players"`
Players map[uint32]qr2.PlayerInfo `json:"players"`
Results map[int][]qr2.RaceResult `json:"results"`
}
@ -33,16 +33,14 @@ func HandleMKWRR(w http.ResponseWriter, r *http.Request) {
}
groupName := query["id"][0]
groups := qr2.GetGroups([]string{}, []string{groupName}, false)
if len(groups) == 0 {
players := qr2.GetRacePlayersForGroup(groupName)
results := qr2.GetRaceResultsForGroup(groupName)
if results == nil {
w.WriteHeader(http.StatusNotFound)
return
}
players := groups[0].Players
results := qr2.GetRaceResultsForGroup(groupName)
if results == nil {
results = map[int][]qr2.RaceResult{}
if players == nil {
players = map[uint32]qr2.PlayerInfo{}
}
var jsonData []byte

View File

@ -52,6 +52,7 @@ type RaceResult struct {
}
var raceResults = map[string]map[int][]RaceResult{} // GroupName -> RaceNumber -> []RaceResult
var racePlayers = map[string]map[uint32]PlayerInfo{} // GroupName -> ProfileID -> historical PlayerInfo
// Timing storage for delta calculation using start/finish times
var raceStartTimings = map[uint32]struct {
@ -655,6 +656,51 @@ func ProcessMKWRaceResult(profileId uint32, playerPid int, finishTimeMs int, cha
if raceResults[group.GroupName] == nil {
raceResults[group.GroupName] = map[int][]RaceResult{}
}
if racePlayers[group.GroupName] == nil {
racePlayers[group.GroupName] = map[uint32]PlayerInfo{}
}
sortedJoinIndex := make([]string, 0, len(group.players))
rawPlayers := make(map[string]map[string]string, len(group.players))
for playerSession := range group.players {
mapData := map[string]string{}
for k, v := range playerSession.Data {
mapData[k] = v
}
if login := playerSession.login; login != nil {
mapData["+ingamesn"] = login.InGameName
} else {
mapData["+ingamesn"] = ""
}
joinIndex := mapData["+joinindex"]
rawPlayers[joinIndex] = mapData
myJoinIndex, _ := strconv.Atoi(joinIndex)
added := false
for i, existingJoinIndex := range sortedJoinIndex {
intJoinIndex, _ := strconv.Atoi(existingJoinIndex)
if intJoinIndex > myJoinIndex {
sortedJoinIndex = append(sortedJoinIndex, "")
copy(sortedJoinIndex[i+1:], sortedJoinIndex[i:])
sortedJoinIndex[i] = joinIndex
added = true
break
}
}
if !added {
sortedJoinIndex = append(sortedJoinIndex, joinIndex)
}
}
for joinIndex, rawPlayer := range rawPlayers {
profileID, err := strconv.ParseUint(rawPlayer["dwc_pid"], 10, 32)
if err != nil {
continue
}
racePlayers[group.GroupName][uint32(profileID)] = buildPlayerInfo(rawPlayer, sortedJoinIndex, joinIndex)
}
raceResults[group.GroupName][group.MKWRaceNumber] = append(raceResults[group.GroupName][group.MKWRaceNumber], raceResultData)
@ -683,6 +729,41 @@ func GetRaceResultsForGroup(groupName string) map[int][]RaceResult {
return copiedRaceResults
}
func StoreRacePlayersForGroup(groupName string, players map[uint32]PlayerInfo) {
mutex.Lock()
defer mutex.Unlock()
if racePlayers[groupName] == nil {
racePlayers[groupName] = map[uint32]PlayerInfo{}
}
for profileID, player := range players {
racePlayers[groupName][profileID] = player
}
}
func GetRacePlayersForGroup(groupName string) map[uint32]PlayerInfo {
mutex.Lock()
defer mutex.Unlock()
groupPlayers, ok := racePlayers[groupName]
if !ok {
return nil
}
copiedPlayers := make(map[uint32]PlayerInfo, len(groupPlayers))
for profileID, player := range groupPlayers {
playerCopy := player
if player.Mii != nil {
playerCopy.Mii = make([]MiiInfo, len(player.Mii))
copy(playerCopy.Mii, player.Mii)
}
copiedPlayers[profileID] = playerCopy
}
return copiedPlayers
}
// saveGroups saves the current groups state to disk.
// Expects the mutex to be locked.
func saveGroups() error {

View File

@ -49,6 +49,59 @@ type RaceInfo struct {
EngineClassID int `json:"cc"`
}
func buildPlayerInfo(rawPlayer map[string]string, sortedJoinIndex []string, joinIndex string) PlayerInfo {
playerInfo := PlayerInfo{
Count: rawPlayer["+localplayers"],
ProfileID: rawPlayer["dwc_pid"],
InGameName: rawPlayer["+ingamesn"],
}
pid, err := strconv.ParseUint(rawPlayer["dwc_pid"], 10, 32)
if err == nil {
if fcGame := rawPlayer["+fcgameid"]; len(fcGame) == 4 {
playerInfo.FriendCode = common.CalcFriendCodeString(uint32(pid), fcGame)
}
}
if rawPlayer["gamename"] == "mariokartwii" {
playerInfo.VersusELO = rawPlayer["ev"]
playerInfo.BattleELO = rawPlayer["eb"]
}
for i := 0; i < 32; i++ {
miiData := rawPlayer["+mii"+strconv.Itoa(i)]
if miiData == "" {
continue
}
playerInfo.Mii = append(playerInfo.Mii, MiiInfo{
MiiData: miiData,
MiiName: rawPlayer["+mii_name"+strconv.Itoa(i)],
})
}
for _, newIndex := range sortedJoinIndex {
if newIndex == joinIndex {
continue
}
if rawPlayer["+conn_"+newIndex] == "" {
playerInfo.ConnMap += "0"
continue
}
playerInfo.ConnMap += rawPlayer["+conn_"+newIndex]
}
playerInfo.ConnFail = rawPlayer["+conn_fail"]
if playerInfo.ConnFail == "" {
playerInfo.ConnFail = "0"
}
playerInfo.Suspend = rawPlayer["dwc_suspend"]
return playerInfo
}
func getGroupsRaw(gameNames []string, groupNames []string) []GroupInfo {
var groupsCopy []GroupInfo
@ -156,57 +209,7 @@ func GetGroups(gameNames []string, groupNames []string, sorted bool) []GroupInfo
for i, group := range groupsCopy {
for joinIndex, rawPlayer := range group.PlayersRaw {
playerInfo := PlayerInfo{
Count: rawPlayer["+localplayers"],
ProfileID: rawPlayer["dwc_pid"],
InGameName: rawPlayer["+ingamesn"],
}
pid, err := strconv.ParseUint(rawPlayer["dwc_pid"], 10, 32)
if err == nil {
if fcGame := rawPlayer["+fcgameid"]; len(fcGame) == 4 {
playerInfo.FriendCode = common.CalcFriendCodeString(uint32(pid), fcGame)
}
}
if rawPlayer["gamename"] == "mariokartwii" {
playerInfo.VersusELO = rawPlayer["ev"]
playerInfo.BattleELO = rawPlayer["eb"]
}
for i := 0; i < 32; i++ {
miiData := rawPlayer["+mii"+strconv.Itoa(i)]
if miiData == "" {
continue
}
playerInfo.Mii = append(playerInfo.Mii, MiiInfo{
MiiData: miiData,
MiiName: rawPlayer["+mii_name"+strconv.Itoa(i)],
})
}
for _, newIndex := range group.SortedJoinIndex {
if newIndex == joinIndex {
continue
}
if rawPlayer["+conn_"+newIndex] == "" {
playerInfo.ConnMap += "0"
continue
}
playerInfo.ConnMap += rawPlayer["+conn_"+newIndex]
}
playerInfo.ConnFail = rawPlayer["+conn_fail"]
if playerInfo.ConnFail == "" {
playerInfo.ConnFail = "0"
}
playerInfo.Suspend = rawPlayer["dwc_suspend"]
groupsCopy[i].Players[joinIndex] = playerInfo
groupsCopy[i].Players[joinIndex] = buildPlayerInfo(rawPlayer, group.SortedJoinIndex, joinIndex)
}
}

View File

@ -82,6 +82,19 @@ func (session *Session) removeFromGroup() {
if len(session.groupPointer.players) == 0 {
logging.Notice("QR2", "Deleting group", aurora.Cyan(session.groupPointer.GroupName))
groupName := session.groupPointer.GroupName
_, ok := raceResults[groupName]
if ok {
go func() {
time.AfterFunc(3*time.Hour, func() {
delete(raceResults, groupName)
delete(racePlayers, groupName)
logging.Notice("QR2", "Deleted race results and players for group", aurora.Cyan(groupName))
})
}()
}
delete(groups, session.groupPointer.GroupName)
} else if session.groupPointer.server == session {
logging.Notice("QR2", "Server down in group", aurora.Cyan(session.groupPointer.GroupName))