package slapshotapi import ( "github.com/pkg/errors" ) // MatchLog represents the raw JSON format of a local match log file. // This differs slightly from the API Game response in structure — the // match log is a flat object with game stats at the top level, whereas // the API response wraps game stats inside a nested "game_stats" field // alongside metadata like region, match type, and creation time. type MatchLog struct { Type string `json:"type"` MatchID string `json:"match_id,omitempty"` Winner string `json:"winner"` Arena string `json:"arena"` PeriodsEnabled string `json:"periods_enabled"` CurrentPeriod string `json:"current_period"` CustomMercyRule string `json:"custom_mercy_rule"` MatchLength string `json:"match_length"` EndReason string `json:"end_reason"` Score Score `json:"score"` Players []Player `json:"players"` } // ParseMatchLog parses a local match log JSON file into a MatchLog struct. func ParseMatchLog(data []byte) (*MatchLog, error) { if len(data) == 0 { return nil, errors.New("data cannot be empty") } log, err := unmarshal[MatchLog](data) if err != nil { return nil, errors.Wrap(err, "unmarshal") } return log, nil } // ToGameStats converts a MatchLog into a GameStats struct, normalizing the // local match log format into the same structure used by the API. func (ml *MatchLog) ToGameStats() GameStats { return GameStats{ Type: ml.Type, Arena: ml.Arena, Score: ml.Score, Winner: ml.Winner, EndReason: ml.EndReason, MatchLength: ml.MatchLength, PeriodsEnabled: ml.PeriodsEnabled, CurrentPeriod: ml.CurrentPeriod, CustomMercyRule: ml.CustomMercyRule, Players: ml.Players, } } // ToGame converts a MatchLog into a Game struct. Since match logs don't // contain all fields present in an API response (region, match_type, // gamemode, created), those fields will be empty. The match_id from the // log (if present) is used as the Game ID. func (ml *MatchLog) ToGame() Game { return Game{ ID: ml.MatchID, GameStats: ml.ToGameStats(), } }