Files
galaxy-game/internal/model/game/game.go
T
Ilia Denisov c9ed52b268 cmd: vote
2026-01-06 07:58:55 +02:00

98 lines
2.3 KiB
Go

package game
import (
"encoding/json"
"fmt"
"iter"
"maps"
"slices"
"strings"
"github.com/google/uuid"
e "github.com/iliadenisov/galaxy/internal/error"
)
type TechSet map[Tech]float64
func (ts TechSet) Value(t Tech) float64 {
if v, ok := ts[t]; ok {
return v
} else {
panic(fmt.Sprintf("TechSet: Value: %s's value not set", t.String()))
}
}
func (ts TechSet) Set(t Tech, v float64) TechSet {
m := maps.Clone(ts)
m[t] = v
return m
}
type Game struct {
ID uuid.UUID `json:"id"`
Age uint `json:"turn"` // Game's turn number
Map Map `json:"map"`
Race []Race `json:"races"`
ShipGroups []ShipGroup `json:"shipGroup,omitempty"`
Fleets []Fleet `json:"fleet,omitempty"`
}
func (g Game) Votes(raceID uuid.UUID) float64 {
// XXX: calculate [Race]Population once when loading Game from Storage?
var pop float64
for i := range g.Map.Planet {
if g.Map.Planet[i].Owner == raceID {
pop += g.Map.Planet[i].Population
}
}
return pop / 1000.
}
func (g Game) PlanetByNumber(number uint) (Planet, error) {
pi := slices.IndexFunc(g.Map.Planet, func(p Planet) bool { return p.Number == number })
if pi < 0 {
return Planet{}, e.NewGameStateError("PlanetByNumber: planet with number=%d not found", number)
}
return g.Map.Planet[pi], nil
}
func (g Game) ShipsInUpgrade(planetNumber uint) iter.Seq[ShipGroup] {
return func(yield func(ShipGroup) bool) {
for sg := range g.ShipGroups {
if g.ShipGroups[sg].Destination == planetNumber && g.ShipGroups[sg].State() == StateUpgrade {
if !yield(g.ShipGroups[sg]) {
break
}
}
}
}
}
func (g Game) raceIndex(name string) (int, error) {
i := slices.IndexFunc(g.Race, func(r Race) bool { return r.Name == name })
if i < 0 {
return i, e.NewRaceUnknownError(name)
}
return i, nil
}
// -----------------------------------------------------------------------------
// validateTypeName always return v without leading and trailing spaces
func validateTypeName(v string) (string, bool) {
s := strings.TrimSpace(v)
if len(s) > 0 {
return s, true
}
// TODO: special symbols AND include error check in all user-input test
return s, false
}
func (g Game) MarshalBinary() (data []byte, err error) {
return json.Marshal(&g)
}
func (g *Game) UnmarshalBinary(data []byte) error {
return json.Unmarshal(data, g)
}