120 lines
4.2 KiB
Go
120 lines
4.2 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql"
|
|
"time"
|
|
)
|
|
|
|
// Player represents an anonymous player identified by a client-generated UUID.
|
|
type Player struct {
|
|
ID int64 `json:"-"`
|
|
ClientID string `json:"client_id"`
|
|
FirstSeen time.Time `json:"first_seen"`
|
|
LastSeen time.Time `json:"last_seen"`
|
|
TotalSessions int `json:"total_sessions"`
|
|
}
|
|
|
|
// PlayerIP tracks distinct IP addresses a player has connected from.
|
|
type PlayerIP struct {
|
|
ID int64 `json:"-"`
|
|
PlayerID int64 `json:"-"`
|
|
IPAddress string `json:"ip_address"`
|
|
FirstSeen time.Time `json:"first_seen"`
|
|
LastSeen time.Time `json:"last_seen"`
|
|
}
|
|
|
|
// GameSession represents a single play session.
|
|
type GameSession struct {
|
|
ID string `json:"session_id"`
|
|
PlayerID int64 `json:"-"`
|
|
Score int `json:"score"`
|
|
LevelReached int `json:"level_reached"`
|
|
LivesUsed int `json:"lives_used"`
|
|
DurationSeconds int `json:"duration_seconds"`
|
|
EndReason string `json:"end_reason"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
EndedAt time.Time `json:"ended_at"`
|
|
}
|
|
|
|
// DeviceInfo holds browser/device fingerprint data captured per session.
|
|
type DeviceInfo struct {
|
|
ID int64 `json:"-"`
|
|
SessionID string `json:"-"`
|
|
IPAddress string `json:"ip_address"`
|
|
UserAgent string `json:"user_agent"`
|
|
Platform string `json:"platform"`
|
|
Language string `json:"language"`
|
|
ScreenWidth sql.NullInt32 `json:"screen_width"`
|
|
ScreenHeight sql.NullInt32 `json:"screen_height"`
|
|
DevicePixelRatio sql.NullFloat64 `json:"device_pixel_ratio"`
|
|
Timezone string `json:"timezone"`
|
|
WebGLRenderer string `json:"webgl_renderer"`
|
|
TouchSupport bool `json:"touch_support"`
|
|
}
|
|
|
|
// HighScore is a denormalized personal-best record, one per player.
|
|
type HighScore struct {
|
|
ID int64 `json:"-"`
|
|
PlayerID int64 `json:"-"`
|
|
Score int `json:"score"`
|
|
SessionID sql.NullString `json:"-"`
|
|
AchievedAt time.Time `json:"achieved_at"`
|
|
}
|
|
|
|
// --- Request/Response types ---
|
|
|
|
// DeviceInfoRequest is the optional device payload in session start.
|
|
type DeviceInfoRequest struct {
|
|
Platform string `json:"platform"`
|
|
Language string `json:"language"`
|
|
ScreenWidth *int `json:"screen_width"`
|
|
ScreenHeight *int `json:"screen_height"`
|
|
DevicePixelRatio *float64 `json:"device_pixel_ratio"`
|
|
Timezone string `json:"timezone"`
|
|
WebGLRenderer string `json:"webgl_renderer"`
|
|
TouchSupport bool `json:"touch_support"`
|
|
}
|
|
|
|
// SessionStartRequest is the JSON body for POST /session/start/.
|
|
type SessionStartRequest struct {
|
|
ClientID string `json:"client_id"`
|
|
Device *DeviceInfoRequest `json:"device"`
|
|
}
|
|
|
|
// SessionEndRequest is the JSON body for POST /session/:id/end/.
|
|
type SessionEndRequest struct {
|
|
Score int `json:"score"`
|
|
LevelReached int `json:"level_reached"`
|
|
LivesUsed int `json:"lives_used"`
|
|
DurationSeconds int `json:"duration_seconds"`
|
|
EndReason string `json:"end_reason"`
|
|
}
|
|
|
|
// LeaderboardEntry is a single row in the leaderboard response.
|
|
type LeaderboardEntry struct {
|
|
ClientID string `json:"client_id"`
|
|
Score int `json:"score"`
|
|
AchievedAt time.Time `json:"achieved_at"`
|
|
}
|
|
|
|
// SessionSummary is a session entry in the player stats response.
|
|
type SessionSummary struct {
|
|
SessionID string `json:"session_id"`
|
|
Score int `json:"score"`
|
|
LevelReached int `json:"level_reached"`
|
|
LivesUsed int `json:"lives_used"`
|
|
DurationSeconds int `json:"duration_seconds"`
|
|
EndReason string `json:"end_reason"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
EndedAt time.Time `json:"ended_at"`
|
|
}
|
|
|
|
// PlayerStatsResponse is the response for GET /player/:client_id/.
|
|
type PlayerStatsResponse struct {
|
|
ClientID string `json:"client_id"`
|
|
TotalSessions int `json:"total_sessions"`
|
|
FirstSeen time.Time `json:"first_seen"`
|
|
HighScore *int `json:"high_score"`
|
|
Sessions []SessionSummary `json:"sessions"`
|
|
}
|