Add daily run rankings

pull/1/head
Flashfyre 2024-03-17 13:18:51 -04:00
parent 71889f7daa
commit ff98047caa
7 changed files with 168 additions and 111 deletions

View File

@ -2,6 +2,8 @@ package api
import (
"encoding/base64"
"encoding/json"
"fmt"
"log"
"net/http"
"time"
@ -34,3 +36,20 @@ func InitDailyRun() {
func (s *Server) HandleSeed(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(dailyRunSeed))
}
// /daily/rankings - fetch daily rankings
func (s *Server) HandleRankings(w http.ResponseWriter, r *http.Request) {
rankings, err := db.GetRankings()
if err != nil {
log.Print("failed to retrieve rankings")
}
response, err := json.Marshal(rankings)
if err != nil {
http.Error(w, fmt.Sprintf("failed to marshal response json: %s", err), http.StatusInternalServerError)
return
}
w.Write(response)
}

View File

@ -52,6 +52,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
case "/daily/seed":
s.HandleSeed(w, r)
case "/daily/rankings":
s.HandleRankings(w, r)
}
}

View File

@ -8,11 +8,12 @@ import (
"os"
"strconv"
"github.com/Flashfyre/pokerogue-server/defs"
"github.com/klauspost/compress/zstd"
)
func GetSystemSaveData(uuid []byte) (SystemSaveData, error) {
var system SystemSaveData
func GetSystemSaveData(uuid []byte) (defs.SystemSaveData, error) {
var system defs.SystemSaveData
save, err := os.ReadFile("userdata/" + hex.EncodeToString(uuid) + "/system.pzs")
if err != nil {
@ -39,8 +40,8 @@ func GetSystemSaveData(uuid []byte) (SystemSaveData, error) {
return system, nil
}
func GetSessionSaveData(uuid []byte, slotId int) (SessionSaveData, error) {
var session SessionSaveData
func GetSessionSaveData(uuid []byte, slotId int) (defs.SessionSaveData, error) {
var session defs.SessionSaveData
fileName := "session"
if slotId != 0 {
@ -72,7 +73,7 @@ func GetSessionSaveData(uuid []byte, slotId int) (SessionSaveData, error) {
return session, nil
}
func ValidateSessionCompleted(session SessionSaveData) bool {
func ValidateSessionCompleted(session defs.SessionSaveData) bool {
switch session.GameMode {
case 0:
return session.WaveIndex == 200

View File

@ -12,6 +12,7 @@ import (
"strconv"
"github.com/Flashfyre/pokerogue-server/db"
"github.com/Flashfyre/pokerogue-server/defs"
"github.com/klauspost/compress/zstd"
)
@ -90,7 +91,7 @@ func (s *Server) HandleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
switch r.URL.Query().Get("datatype") {
case "0": // System
var system SystemSaveData
var system defs.SystemSaveData
err = json.NewDecoder(r.Body).Decode(&system)
if err != nil {
http.Error(w, fmt.Sprintf("failed to decode request body: %s", err), http.StatusBadRequest)
@ -145,7 +146,7 @@ func (s *Server) HandleSavedataUpdate(w http.ResponseWriter, r *http.Request) {
fileName += strconv.Itoa(slotId)
}
var session SessionSaveData
var session defs.SessionSaveData
err = json.NewDecoder(r.Body).Decode(&session)
if err != nil {
http.Error(w, fmt.Sprintf("failed to decode request body: %s", err), http.StatusBadRequest)
@ -268,7 +269,7 @@ func (s *Server) HandleSavedataClear(w http.ResponseWriter, r *http.Request) {
return
}
var session SessionSaveData
var session defs.SessionSaveData
err = json.NewDecoder(r.Body).Decode(&session)
if err != nil {
http.Error(w, fmt.Sprintf("failed to decode request body: %s", err), http.StatusBadRequest)

View File

@ -1,5 +1,9 @@
package db
import (
"github.com/Flashfyre/pokerogue-server/defs"
)
func TryAddDailyRun(seed string) error {
_, err := handle.Exec("INSERT INTO dailyRuns (seed, date) VALUES (?, UTC_DATE()) ON DUPLICATE KEY UPDATE date = date", seed)
if err != nil {
@ -8,3 +12,26 @@ func TryAddDailyRun(seed string) error {
return nil
}
func GetRankings() ([]defs.DailyRanking, error) {
var rankings []defs.DailyRanking
results, err := handle.Query("SELECT RANK() OVER (ORDER BY sc.score DESC, sc.timestamp), a.username, sc.score FROM seedCompletions sc JOIN dailyRuns dr ON dr.seed = sc.seed JOIN accounts a ON sc.uuid = a.uuid WHERE dr.date = UTC_DATE()")
if err != nil {
return rankings, err
}
defer results.Close()
for results.Next() {
ranking := defs.DailyRanking{}
err = results.Scan(&ranking.Rank, &ranking.Username, &ranking.Score)
if err != nil {
return rankings, err
}
rankings = append(rankings, ranking)
}
return rankings, nil
}

7
defs/daily.go Normal file
View File

@ -0,0 +1,7 @@
package defs
type DailyRanking struct {
Rank int `json:"rank"`
Username string `json:"username"`
Score int `json:"score"`
}

View File

@ -1,103 +1,103 @@
package api
type SystemSaveData struct {
TrainerId int `json:"trainerId"`
SecretId int `json:"secretId"`
Gender int `json:"gender"`
DexData DexData `json:"dexData"`
StarterMoveData StarterMoveData `json:"starterMoveData"`
StarterEggMoveData StarterEggMoveData `json:"starterEggMoveData"`
GameStats GameStats `json:"gameStats"`
Unlocks Unlocks `json:"unlocks"`
AchvUnlocks AchvUnlocks `json:"achvUnlocks"`
VoucherUnlocks VoucherUnlocks `json:"voucherUnlocks"`
VoucherCounts VoucherCounts `json:"voucherCounts"`
Eggs []EggData `json:"eggs"`
GameVersion string `json:"gameVersion"`
Timestamp int `json:"timestamp"`
}
type DexData map[int]DexEntry
type DexEntry struct {
SeenAttr interface{} `json:"seenAttr"` // integer or string
CaughtAttr interface{} `json:"caughtAttr"` // integer or string
NatureAttr int `json:"natureAttr"`
SeenCount int `json:"seenCount"`
CaughtCount int `json:"caughtCount"`
HatchedCount int `json:"hatchedCount"`
Ivs []int `json:"ivs"`
}
type StarterMoveData map[int]interface{}
type StarterEggMoveData map[int]int
type GameStats interface{}
type Unlocks map[int]bool
type AchvUnlocks map[string]int
type VoucherUnlocks map[string]int
type VoucherCounts map[string]int
type EggData struct {
Id int `json:"id"`
GachaType GachaType `json:"gachaType"`
HatchWaves int `json:"hatchWaves"`
Timestamp int `json:"timestamp"`
}
type GachaType int
type SessionSaveData struct {
Seed string `json:"seed"`
PlayTime int `json:"playTime"`
GameMode GameMode `json:"gameMode"`
Party []PokemonData `json:"party"`
EnemyParty []PokemonData `json:"enemyParty"`
Modifiers []PersistentModifierData `json:"modifiers"`
EnemyModifiers []PersistentModifierData `json:"enemyModifiers"`
Arena ArenaData `json:"arena"`
PokeballCounts PokeballCounts `json:"pokeballCounts"`
Money int `json:"money"`
Score int `json:"score"`
WaveIndex int `json:"waveIndex"`
BattleType BattleType `json:"battleType"`
Trainer TrainerData `json:"trainer"`
GameVersion string `json:"gameVersion"`
Timestamp int `json:"timestamp"`
}
type GameMode int
type PokemonData interface{}
type PersistentModifierData interface{}
type ArenaData interface{}
type PokeballCounts map[string]int
type BattleType int
type TrainerData interface{}
type SessionHistoryData struct {
Seed string `json:"seed"`
PlayTime int `json:"playTime"`
Result SessionHistoryResult `json:"sessionHistoryResult"`
GameMode GameMode `json:"gameMode"`
Party []PokemonData `json:"party"`
Modifiers []PersistentModifierData `json:"modifiers"`
Money int `json:"money"`
Score int `json:"score"`
WaveIndex int `json:"waveIndex"`
BattleType BattleType `json:"battleType"`
GameVersion string `json:"gameVersion"`
Timestamp int `json:"timestamp"`
}
type SessionHistoryResult int
package defs
type SystemSaveData struct {
TrainerId int `json:"trainerId"`
SecretId int `json:"secretId"`
Gender int `json:"gender"`
DexData DexData `json:"dexData"`
StarterMoveData StarterMoveData `json:"starterMoveData"`
StarterEggMoveData StarterEggMoveData `json:"starterEggMoveData"`
GameStats GameStats `json:"gameStats"`
Unlocks Unlocks `json:"unlocks"`
AchvUnlocks AchvUnlocks `json:"achvUnlocks"`
VoucherUnlocks VoucherUnlocks `json:"voucherUnlocks"`
VoucherCounts VoucherCounts `json:"voucherCounts"`
Eggs []EggData `json:"eggs"`
GameVersion string `json:"gameVersion"`
Timestamp int `json:"timestamp"`
}
type DexData map[int]DexEntry
type DexEntry struct {
SeenAttr interface{} `json:"seenAttr"` // integer or string
CaughtAttr interface{} `json:"caughtAttr"` // integer or string
NatureAttr int `json:"natureAttr"`
SeenCount int `json:"seenCount"`
CaughtCount int `json:"caughtCount"`
HatchedCount int `json:"hatchedCount"`
Ivs []int `json:"ivs"`
}
type StarterMoveData map[int]interface{}
type StarterEggMoveData map[int]int
type GameStats interface{}
type Unlocks map[int]bool
type AchvUnlocks map[string]int
type VoucherUnlocks map[string]int
type VoucherCounts map[string]int
type EggData struct {
Id int `json:"id"`
GachaType GachaType `json:"gachaType"`
HatchWaves int `json:"hatchWaves"`
Timestamp int `json:"timestamp"`
}
type GachaType int
type SessionSaveData struct {
Seed string `json:"seed"`
PlayTime int `json:"playTime"`
GameMode GameMode `json:"gameMode"`
Party []PokemonData `json:"party"`
EnemyParty []PokemonData `json:"enemyParty"`
Modifiers []PersistentModifierData `json:"modifiers"`
EnemyModifiers []PersistentModifierData `json:"enemyModifiers"`
Arena ArenaData `json:"arena"`
PokeballCounts PokeballCounts `json:"pokeballCounts"`
Money int `json:"money"`
Score int `json:"score"`
WaveIndex int `json:"waveIndex"`
BattleType BattleType `json:"battleType"`
Trainer TrainerData `json:"trainer"`
GameVersion string `json:"gameVersion"`
Timestamp int `json:"timestamp"`
}
type GameMode int
type PokemonData interface{}
type PersistentModifierData interface{}
type ArenaData interface{}
type PokeballCounts map[string]int
type BattleType int
type TrainerData interface{}
type SessionHistoryData struct {
Seed string `json:"seed"`
PlayTime int `json:"playTime"`
Result SessionHistoryResult `json:"sessionHistoryResult"`
GameMode GameMode `json:"gameMode"`
Party []PokemonData `json:"party"`
Modifiers []PersistentModifierData `json:"modifiers"`
Money int `json:"money"`
Score int `json:"score"`
WaveIndex int `json:"waveIndex"`
BattleType BattleType `json:"battleType"`
GameVersion string `json:"gameVersion"`
Timestamp int `json:"timestamp"`
}
type SessionHistoryResult int