osn

package module
v0.0.0-...-86e69cd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 20, 2024 License: MIT Imports: 8 Imported by: 0

README

wits-osn

Data format and conversion functions for legacy data representation of Outwitters Sports Network (OSN), host of replays for the mobile game Outwitters2.

References

CodePenguin's site which this schema was reverse-engineered from:
https://osn.codepenguin.com/replays
Inspiration for the Object Relational Mapping in `db/`:
https://okmij.org/ftp/Haskell/HList-ext.pdf

Documentation

Index

Constants

View Source
const TimeLayout = "2006-01-02 15:04:05"

For go's time.Parse this must always be this same date and time.

View Source
const UNKNOWN_MATCH_ID = GameID("")

Variables

This section is empty.

Functions

func EnumValuesFor

func EnumValuesFor[T EnumType](limit T) []T

Convenience method for listing the enum values from UNKNOWN (0) to its LIMIT.

func ParseRawReplay

func ParseRawReplay(filedata []byte) (string, []byte, error)

Types

type BaseHealth

type BaseHealth uint

type Boolish

type Boolish bool

Represents a boolean-like value that may be a bool, an int or a string. Implements JSON-codec and SQL-codec operations for natural encoding/decoding.

If non-boolean, a 0 or "0" or "" value is false and any other value is true. When serializing, it uses the native boolean type.

func (Boolish) MarshalJSON

func (b Boolish) MarshalJSON() ([]byte, error)

func (*Boolish) Scan

func (b *Boolish) Scan(value interface{}) error

Similar to the conversion rules above but any non-{0|1} integer is an error, this and string conversion are consistent with driver.Bool translation.

func (*Boolish) UnmarshalJSON

func (b *Boolish) UnmarshalJSON(encoded []byte) error

func (Boolish) Value

func (b Boolish) Value() (driver.Value, error)

type EnumType

type EnumType interface {
	~uint8
	fmt.Stringer

	// Returns true if the represented value is valid.
	// The uint8(0) value ("UNKNOWN") is also considered valid.
	IsValid() bool
}

Dependent type for EnumTable, the shape that all enums are assumed to have.

Within this project, all enum-compatible values must satisfy this interface. An underlying type of uint8 (anything larger should be promoted to a Table) and an ability to be converted into a string. The string equivalent will be used as the human-readable format, while elsewhere the integer value is used.

It is assumed that the zero value for enums has UNKNOWN-equivalent semantics.

type FetchStatus

type FetchStatus uint8

There is a finite, unchanging set of status values based on the progress of processing a sing replay from reading its listing through transforming its encoding and reducing combinatoric symmetries.

const (
	STATUS_UNKNOWN FetchStatus = iota
	STATUS_LISTED
	STATUS_FETCHED
	STATUS_UNWRAPPED
	STATUS_CONVERTED
	STATUS_CANONICAL
	STATUS_VALIDATED
	STATUS_INDEXED
	STATUS_INVALID
	STATUS_LEGACY
	FetchStatusRange
)

func (FetchStatus) IsValid

func (status FetchStatus) IsValid() bool

func (FetchStatus) String

func (status FetchStatus) String() string

type GameID

type GameID string

Extension of a game's ID which automatically shortens it when marshaling.

func (GameID) MarshalJSON

func (id GameID) MarshalJSON() ([]byte, error)

Marshal the game ID (removing 48-character common prefix all games share).

func (GameID) ShortID

func (id GameID) ShortID() string

func (*GameID) UnmarshalJSON

func (id *GameID) UnmarshalJSON(encoded []byte) error

type GameOverData

type GameOverData struct {
	Competitive Boolish           `json:"isLeagueMatch"`
	Online      Boolish           `json:"-"`
	Winners     []OsnPlayerUpdate `json:"winners"`
	Losers      []OsnPlayerUpdate `json:"losers"`
}

type GameStatus

type GameStatus int

type HexCoord

type HexCoord struct {
	Column int `json:"positionI"`
	Row    int `json:"positionJ"`
}

func (HexCoord) AsVector

func (coord HexCoord) AsVector() []int

type LeagueEnum

type LeagueEnum uint8
const (
	LEAGUE_UNKNOWN LeagueEnum = iota
	LEAGUE_FLUFFY
	LEAGUE_CLEVER
	LEAGUE_GIFTED
	LEAGUE_MASTER
	LEAGUE_SUPERTITAN
	LeagueRange
)

Using iota here because I don't plan on ever changing the OSN representation. See github.com/kevindamm/wits-go for a more forward-compatible enumeration.

func ParseLeague

func ParseLeague(str_uint string) LeagueEnum

Parse the integer representation in the provided string, returns LEAGUE_UNKNOWN if there was an error or no league with that number.

func (LeagueEnum) IsValid

func (league LeagueEnum) IsValid() bool

func (LeagueEnum) String

func (league LeagueEnum) String() string

type LeagueRank

type LeagueRank uint8

The player's rank within their current group. Players are placed in groups of around 100 when entering a league. Each of these divisions is given a name but historical data of that is not included in the replay or index data sent from OSN, and is not relevant enough to the replay analysis to be archived with the replay data.

func (LeagueRank) IsValid

func (rank LeagueRank) IsValid() bool

func (LeagueRank) String

func (rank LeagueRank) String() string

type LegacyMap

type LegacyMap struct {
	MapID uint8  `json:"map_id"`
	Name  string `json:"name"`

	// The number of players this map can accommodate.
	// Use 0 for a player count on deprecated maps
	RoleCount int `json:"role_count"`

	// Embedded type avoids the extra indirection
	// while facilitating compact table representation.
	Shortname string `json:"-"`

	LegacyMapDetails
}

func UnknownMap

func UnknownMap() LegacyMap

type LegacyMapDetails

type LegacyMapDetails struct {
	Width    int            `json:"columns"`
	Height   int            `json:"rows"`
	Theme    int            `json:"theme"`
	Defaults map[string]int `json:"defaults"`
	Init     []MapTileInit  `json:"background"`
}

func (*LegacyMapDetails) Scan

func (details *LegacyMapDetails) Scan(value driver.Value) error

Recovers the structure from a database driver using JSON deserialization.

func (LegacyMapDetails) Value

func (details LegacyMapDetails) Value() (driver.Value, error)

Hands the structure to a database driver using JSON serializagion.

type LegacyMatch

type LegacyMatch struct {
	MatchIndex  int64     `json:"-"`
	MatchHash   GameID    `json:"gameid"`
	OsnIndex    int       `json:"id,omitempty"`
	Competitive bool      `json:"competitive"`
	Season      int       `json:"season"`
	CreatedTime time.Time `json:"created"`
	MapID       int       `json:"mapid"`
	TurnCount   int       `json:"turn_count"`

	Version     int         `json:"engine"`
	FetchStatus FetchStatus `json:"-"`

	Players []PlayerRole `json:"players,omitempty"`
}

The metadata of a single match between two or four players. Everything but the social signals (views/likes) and replay (player turns).

var UNKNOWN_MATCH LegacyMatch = LegacyMatch{
	MatchHash: UNKNOWN_MATCH_ID,
}

type LegacyMatchWithReplay

type LegacyMatchWithReplay struct {
	LegacyMatch
	OsnGameState

	Terminal GameOverData `json:"gameOverData,omitempty"`
	Replay   OsnReplay    `json:"replay"`
}

Contains both the metadata (as LegacyMatch) and player turns (as ReplayData).

type LegacyReplayMetadata

type LegacyReplayMetadata struct {
	Index       string `json:"id"`            // integer index into sequential games
	GameID      string `json:"gameid"`        // hash of game creation
	NumPlayers  string `json:"gametype"`      // solo ("2") vs duo ("4")
	LeagueMatch string `json:"isleaguematch"` // "1" if true
	Created     string `json:"created"`       // 2012-08-05 14:33:21
	Season      string `json:"season"`        // integer ("1")

	// Runtime is parameterized by engine version and map definition.
	OsnVersion string `json:"engine"`     // integer #=< 1063, ("1000" is v1)
	MapID      string `json:"mapid"`      // relates to indexed maps, (id "4")
	MapName    string `json:"map_title"`  // display name ("Glitch"), redundant
	MapTheme   string `json:"map_raceid"` // enumeration, e.g. "1" is Feedback

	// These aren't persisted in the database but appear in the OSN index.
	TurnCount string `json:"turn_count"` // integer "34"
	ViewCount string `json:"viewcount"`  // integer "116"
	LikeCount string `json:"like_count"` // integer "0"

	Player1_ID     string `json:"p1_playerid"`   // integer "1",
	Player1_Name   string `json:"p1_playername"` // utf8 name "Syvan",
	Player1_League string `json:"p1_leagueid"`   // OsnLeagueEnum
	Player1_Race   string `json:"p1_raceid"`     // OsnRaceEnum
	Player1_Wins   string `json:"p1_winner"`     // boolish "1",
	Player1_BaseHP string `json:"p1_basehp"`     // #=< "5",

	Player2_ID     string `json:"p2_playerid"`   //: integer "2",
	Player2_Name   string `json:"p2_playername"` //: utf8 name "Alvendor",
	Player2_League string `json:"p2_leagueid"`   //: OsnLeagueEnum
	Player2_Race   string `json:"p2_raceid"`     //: OsnRaceEnum
	Player2_Wins   string `json:"p2_winner"`     //: boolish "0",
	Player2_BaseHP string `json:"p2_basehp"`     //: #=< "0",

	Player3_ID     string `json:"p3_playerid,omitempty"`   //: may be null
	Player3_Name   string `json:"p3_playername,omitempty"` //: may be null
	Player3_League string `json:"p3_leagueid,omitempty"`   //: may be null
	Player3_Race   string `json:"p3_raceid,omitempty"`     //: may be null
	Player3_Wins   string `json:"p3_winner,omitempty"`     //: may be null
	Player3_BaseHP string `json:"p3_basehp,omitempty"`     //: may be null

	Player4_ID     string `json:"p4_playerid,omitempty"`   //: may be null
	Player4_Name   string `json:"p4_playername,omitempty"` //: may be null
	Player4_League string `json:"p4_leagueid,omitempty"`   //: may be null
	Player4_Race   string `json:"p4_raceid,omitempty"`     //: may be null
	Player4_Wins   string `json:"p4_winner,omitempty"`     //: may be null
	Player4_BaseHP string `json:"p4_basehp,omitempty"`     //: may be null

	FirstPlayer string `json:"first_playerid"` // integer, matches playerid above
}

The (unaltered) representation of match-related metadata from OSN.

This includes everything in the match entries of the json response for "recent replays".

func (*LegacyReplayMetadata) Players

func (metadata *LegacyReplayMetadata) Players() []Player

func (LegacyReplayMetadata) String

func (metadata LegacyReplayMetadata) String() string

Emits the JSON representation as well as the ID value which is typically not part of the JSON payload. Useful for debugging, but the rowid `id` value is transient, it may change at the next VACUUM or repartitioning.

func (*LegacyReplayMetadata) ToLegacyMatch

func (metadata *LegacyReplayMetadata) ToLegacyMatch() LegacyMatch

type MapTileInit

type MapTileInit struct {
	I     int         `json:"i"`
	J     int         `json:"j"`
	Type  MapTileType `json:"type"`
	Sub   SpriteIndex `json:"sub,omitempty"`
	Owner PlayerIndex `json:"owner,omitempty"`
}

type MapTileType

type MapTileType uint8

type OsnGameState

type OsnGameState struct {
	CapturedTiles []TileState `json:"captureTileStates"`
	CurrentPawnID int         `json:"currentPawnID"`
	CurrentPlayer PlayerIndex `json:"currentPlayer"`

	Base0_HP BaseHealth `json:"hp_base0"`
	Base1_HP BaseHealth `json:"hp_base1"`
	Outcome  GameStatus `json:"outcome,omitempty"`

	MapName  string          `json:"mapName"`
	MapTheme string          `json:"mapTheme"`
	Settings OsnRoleSettings `json:"settings"`

	TurnCount  int          `json:"turnCount,omitempty"`
	Units      []UnitStatus `json:"units"`
	UsedSpawns []UsedSpawn  `json:"usedSpawns,omitempty"`
}

type OsnPlayerAction

type OsnPlayerAction interface {
	Name() string
	AsDict() map[string]interface{}
}

type OsnPlayerTurn

type OsnPlayerTurn struct {
	Actions []OsnPlayerAction
	State   OsnGameState `json:"state"`
}

type OsnPlayerUpdate

type OsnPlayerUpdate struct {
	BaseHealth int             `json:"baseHealth"`
	Color      PlayerColorEnum `json:"color"`
	GCID       string          `json:"gcID"`
	Delta      int             `json:"leaguePointsDelta"`
	PlayerName string          `json:"name"`
	Owner      int             `json:"owner"`
	Race       int             `json:"race"`
	Team       int             `json:"team"`

	NewLeague     LeagueEnum `json:"newLeague"`
	NewLeagueRank LeagueRank `json:"newLeagueRank"`
	OldLeague     LeagueEnum `json:"oldLeague"`
	OldLeagueRank LeagueRank `json:"oldLeagueRank"`

	RankDirection int     `json:"rankDirection"`
	Demoted       Boolish `json:"wasDemoted"`
	Promoted      Boolish `json:"wasPromoted"`
}

Matches the data layout of an OSN player update (from game over data).

type OsnReplay

type OsnReplay []OsnReplayData

type OsnReplayData

type OsnReplayData struct {
	Turns []OsnPlayerTurn
}

ReplayData is a sequence of player turns, each composed of spawns & actions.

The player turn is composed of a partially-ordered sequence of actions, the actions themselves are polymorphic under the interface type OsnPlayerAction.

type OsnRoleSettings

type OsnRoleSettings struct {
	PlayerID   int64  `json:"id"`
	GCID       string `json:"gcID"`
	PlayerName string `json:"name"`

	ActionPoints uint `json:"actionPoints"`

	Team     uint         `json:"team"`
	Color    uint         `json:"color"`
	UnitRace UnitRaceEnum `json:"race"`

	BaseTheme   uint    `json:"basePref,omitempty"`
	Invited     Boolish `json:"isInvited,omitempty"`
	Placeholder Boolish `json:"isPlaceHolder,omitempty"`
}

type Player

type Player struct {
	RowID int64  `json:"-" orm:"rowid,pk"`
	GCID  string `json:"gcid,omitempty" orm:"gcid?,unique"`
	Name  string `json:"name" orm:"name!Unknown,unique"`
}
var UNKNOWN_PLAYER Player = Player{
	RowID: 0,
	GCID:  "",
	Name:  "",
}

func NewPlayer

func NewPlayer(id int64, name string) Player

Simple (no GCID) constructor for a Player instance.

type PlayerColorEnum

type PlayerColorEnum uint8

This is actually arbitrary but provided for internal consistency.

const (
	PLAYERCOLOR_UNKNOWN PlayerColorEnum = iota
	PLAYERCOLOR_BLUE
	PLAYERCOLOR_RED
	PLAYERCOLOR_GREEN
	PLAYERCOLOR_GOLD
	PlayerColorRange
)

func (PlayerColorEnum) String

func (color PlayerColorEnum) String() string

type PlayerIndex

type PlayerIndex uint8

type PlayerRole

type PlayerRole struct {
	Player    `json:"player" orm:"fk(players)"`
	UnitRace  UnitRaceEnum    `json:"race" orm:"fk(races)"`
	BaseTheme int             `json:"theme" orm:"-"`
	TurnOrder PlayerColorEnum `json:"color" orm:"turn_order"`

	// The remaining actions for the player at the latest turn.
	//
	// This is useful for maintaining a view of the state derived from all of the
	// player's previous turns but doesn't need to be persisted in the database.
	Actions uint `json:"wits" orm:"-"`

	// These are derived from the standings table which refer to the role record.
	RankBefore PlayerStanding `json:"rank_prev" orm:"--from fk(standings.until)"`
	RankAfter  PlayerStanding `json:"rank_next,omitempty" orm:"--from fk(standings.after)"`
}

Represents an assignment of a Player (identifier) with match participation.

type PlayerStanding

type PlayerStanding struct {
	League LeagueEnum
	Rank   LeagueRank
	Points uint16
	Delta  int8 // difference since [points] of previous standings.
}

An ELO-like measurement [points], and the player's league + standings status.

func NewStanding

func NewStanding(league LeagueEnum, rank LeagueRank, points uint16, delta int8) (PlayerStanding, error)

func UnknownStanding

func UnknownStanding() PlayerStanding

func (PlayerStanding) PointsBefore

func (ranked PlayerStanding) PointsBefore() uint16

type SpriteIndex

type SpriteIndex uint8

type TileState

type TileState struct {
	I uint `json:"tileI"`
	J uint `json:"tileJ"`

	Type TileType `json:"tileType"`
}

Used in `captureTileStates[]` of the game board state.

type TileType

type TileType int

TODO refine this enum (or drop from ETL)

type UnitClass

type UnitClass int

TODO populate enum

type UnitRaceEnum

type UnitRaceEnum uint8

Enumeration of race; determines special unit and affects visual appearance. Satisfies Resource[RaceEnum] for inclusion in database tables.

const (
	RACE_UNKNOWN UnitRaceEnum = iota
	RACE_FEEDBACK
	RACE_ADORABLES
	RACE_SCALLYWAGS
	RACE_VEGGIENAUTS
	UnitRaceRange
)

func (UnitRaceEnum) IsValid

func (race UnitRaceEnum) IsValid() bool

func (UnitRaceEnum) String

func (race UnitRaceEnum) String() string

type UnitSpecialEnum

type UnitSpecialEnum uint8

Each race has one special unit associated with it. They share the enumeration ordering with UnitRaceEnum for ease of conversion.

const (
	SPECIAL_UNKNOWN UnitSpecialEnum = iota
	SPECIAL_SCRAMBLER
	SPECIAL_MOBI
	SPECIAL_BOMBSHELL
	SPECIAL_BRAMBLE
	UnitSpecialRange
)

func (UnitSpecialEnum) IsValid

func (special UnitSpecialEnum) IsValid() bool

func (UnitSpecialEnum) String

func (special UnitSpecialEnum) String() string

type UnitStatus

type UnitStatus struct {
	AltHealth uint            `json:"altHealth"`
	Class     UnitClass       `json:"class"`
	Color     PlayerColorEnum `json:"color"`

	HasAttacked    Boolish `json:"hasAttacked"`
	HasMoved       Boolish `json:"hasMoved"`
	HasTransformed Boolish `json:"hasTransformed"`

	Health     uint    `json:"health"`
	Identifier uint    `json:"identifier"`
	IsAlt      Boolish `json:"isAlt"`
	Owner      uint    `json:"owner"` // player turn order?
	Team       uint    `json:"team"`

	Parent      int `json:"parent"`      // -1 if no parentage
	SpawnedFrom int `json:"spawnedFrom"` // -1 if from spawn tile

	PositionI uint         `json:"positionI"`
	PositionJ uint         `json:"positionJ"`
	UnitRace  UnitRaceEnum `json:"race"`
}

type UsedSpawn

type UsedSpawn struct {
	SpawnX int `json:"ix"`
	SpawnY int `json:"iy"`
}

type WireFormat

type WireFormat struct {
	Wrapper outer `json:"viewResponse"` // Path reference of an `.hxm` file.
}

This is the format as returned by the web service for a single game replay.

It is a shallow wrapper around the actual game replay, containing four dictionary entries, one of which is a string representation of the game.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL