game stats shows planes and population

This commit is contained in:
Ilia Denisov
2026-04-26 21:12:51 +02:00
parent fe829285a6
commit b4591cabd4
11 changed files with 84 additions and 22 deletions
+16 -1
View File
@@ -152,10 +152,25 @@ func GameState(configure func(*Param)) (s game.State, err error) {
Players: make([]game.PlayerState, len(g.Race)), Players: make([]game.PlayerState, len(g.Race)),
} }
planetCount := make(map[uuid.UUID]uint)
population := make(map[uuid.UUID]game.Float)
for i := range g.Map.Planet {
p := &g.Map.Planet[i]
if p.Owner == nil {
continue
}
owner := *p.Owner
planetCount[owner] += 1
population[owner] += p.Population
}
for i := range g.Race { for i := range g.Race {
r := &g.Race[i] r := &g.Race[i]
result.Players[i].ID = r.ID result.Players[i].ID = r.ID
result.Players[i].Name = r.Name result.Players[i].RaceName = r.Name
result.Players[i].Planets = planetCount[r.ID]
result.Players[i].Population = population[r.ID]
result.Players[i].Extinct = r.Extinct result.Players[i].Extinct = r.Extinct
} }
+3 -1
View File
@@ -11,6 +11,8 @@ type State struct {
type PlayerState struct { type PlayerState struct {
ID uuid.UUID ID uuid.UUID
Name string RaceName string
Planets uint
Population Float
Extinct bool Extinct bool
} }
+3 -1
View File
@@ -99,7 +99,9 @@ func stateResponse(s game.State) rest.StateResponse {
} }
for i := range s.Players { for i := range s.Players {
result.Players[i].ID = s.Players[i].ID result.Players[i].ID = s.Players[i].ID
result.Players[i].Name = s.Players[i].Name result.Players[i].RaceName = s.Players[i].RaceName
result.Players[i].Planets = s.Players[i].Planets
result.Players[i].Population = s.Players[i].Population.F()
result.Players[i].Extinct = s.Players[i].Extinct result.Players[i].Extinct = s.Players[i].Extinct
} }
return *result return *result
+2 -2
View File
@@ -9,14 +9,14 @@ import (
) )
func InitHandler(c *gin.Context, executor CommandExecutor) { func InitHandler(c *gin.Context, executor CommandExecutor) {
var init rest.Init var init rest.InitRequest
if errorResponse(c, c.ShouldBindJSON(&init)) { if errorResponse(c, c.ShouldBindJSON(&init)) {
return return
} }
races := make([]string, len(init.Races)) races := make([]string, len(init.Races))
for i := range init.Races { for i := range init.Races {
races[i] = init.Races[i].Name races[i] = init.Races[i].RaceName
} }
s, err := executor.GenerateGame(races) s, err := executor.GenerateGame(races)
+4 -4
View File
@@ -68,12 +68,12 @@ func limitTestingRouter() *gin.Engine {
return r return r
} }
func generateInitRequest(races int) rest.Init { func generateInitRequest(races int) rest.InitRequest {
request := rest.Init{ request := rest.InitRequest{
Races: make([]rest.Race, races), Races: make([]rest.InitRace, races),
} }
for i := range request.Races { for i := range request.Races {
request.Races[i] = rest.Race{Name: raceName(i)} request.Races[i] = rest.InitRace{RaceName: raceName(i)}
} }
return request return request
} }
+3 -1
View File
@@ -50,7 +50,9 @@ func TestGetStatus(t *testing.T) {
assert.Len(t, stateResponse.Players, 10) assert.Len(t, stateResponse.Players, 10)
for i := range stateResponse.Players { for i := range stateResponse.Players {
assert.NoError(t, uuid.Validate(stateResponse.Players[i].ID.String())) assert.NoError(t, uuid.Validate(stateResponse.Players[i].ID.String()))
assert.Equal(t, raceName(i), stateResponse.Players[i].Name) assert.Equal(t, raceName(i), stateResponse.Players[i].RaceName)
assert.Equal(t, uint(3), stateResponse.Players[i].Planets)
assert.Equal(t, 2000., stateResponse.Players[i].Population)
assert.False(t, stateResponse.Players[i].Extinct) assert.False(t, stateResponse.Players[i].Extinct)
} }
} }
+21
View File
@@ -39,6 +39,13 @@ func TestGetTurn(t *testing.T) {
assert.NotEqual(t, uuid.Nil, uuid.MustParse(initResponse.ID.String())) assert.NotEqual(t, uuid.Nil, uuid.MustParse(initResponse.ID.String()))
assert.Equal(t, uint(0), initResponse.Turn) assert.Equal(t, uint(0), initResponse.Turn)
assert.Equal(t, uint(0), initResponse.Stage) assert.Equal(t, uint(0), initResponse.Stage)
for i := range initResponse.Players {
assert.NoError(t, uuid.Validate(initResponse.Players[i].ID.String()))
assert.Equal(t, raceName(i), initResponse.Players[i].RaceName)
assert.Equal(t, uint(3), initResponse.Players[i].Planets)
assert.Equal(t, 2000., initResponse.Players[i].Population)
assert.False(t, initResponse.Players[i].Extinct)
}
// generate next turn // generate next turn
@@ -54,6 +61,13 @@ func TestGetTurn(t *testing.T) {
assert.Equal(t, initResponse.ID, turnResponse.ID) assert.Equal(t, initResponse.ID, turnResponse.ID)
assert.Equal(t, uint(1), turnResponse.Turn) assert.Equal(t, uint(1), turnResponse.Turn)
assert.Equal(t, uint(0), turnResponse.Stage) assert.Equal(t, uint(0), turnResponse.Stage)
for i := range turnResponse.Players {
assert.NoError(t, uuid.Validate(turnResponse.Players[i].ID.String()))
assert.Equal(t, raceName(i), turnResponse.Players[i].RaceName)
assert.Equal(t, uint(3), turnResponse.Players[i].Planets)
assert.Equal(t, 2000., turnResponse.Players[i].Population)
assert.False(t, turnResponse.Players[i].Extinct)
}
// validate status // validate status
@@ -67,4 +81,11 @@ func TestGetTurn(t *testing.T) {
assert.Equal(t, initResponse.ID, stateResponse.ID) assert.Equal(t, initResponse.ID, stateResponse.ID)
assert.Equal(t, uint(1), stateResponse.Turn) assert.Equal(t, uint(1), stateResponse.Turn)
assert.Equal(t, uint(0), stateResponse.Stage) assert.Equal(t, uint(0), stateResponse.Stage)
for i := range stateResponse.Players {
assert.NoError(t, uuid.Validate(stateResponse.Players[i].ID.String()))
assert.Equal(t, raceName(i), stateResponse.Players[i].RaceName)
assert.Equal(t, uint(3), stateResponse.Players[i].Planets)
assert.Equal(t, 2000., stateResponse.Players[i].Population)
assert.False(t, stateResponse.Players[i].Extinct)
}
} }
+3
View File
@@ -4,6 +4,7 @@ go 1.26.1
require ( require (
galaxy/postgres v0.0.0-00010101000000-000000000000 galaxy/postgres v0.0.0-00010101000000-000000000000
galaxy/redisconn v0.0.0-00010101000000-000000000000
github.com/alicebob/miniredis/v2 v2.37.0 github.com/alicebob/miniredis/v2 v2.37.0
github.com/disciplinedware/go-confusables v0.1.1 github.com/disciplinedware/go-confusables v0.1.1
github.com/getkin/kin-openapi v0.135.0 github.com/getkin/kin-openapi v0.135.0
@@ -43,6 +44,8 @@ require (
github.com/lib/pq v1.10.9 // indirect github.com/lib/pq v1.10.9 // indirect
github.com/mfridman/interpolate v0.0.2 // indirect github.com/mfridman/interpolate v0.0.2 // indirect
github.com/pressly/goose/v3 v3.27.1 // indirect github.com/pressly/goose/v3 v3.27.1 // indirect
github.com/redis/go-redis/extra/rediscmd/v9 v9.18.0 // indirect
github.com/redis/go-redis/extra/redisotel/v9 v9.18.0 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect github.com/sethvargo/go-retry v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sync v0.20.0 // indirect golang.org/x/sync v0.20.0 // indirect
+4
View File
@@ -224,6 +224,10 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pressly/goose/v3 v3.27.1 h1:6uEvcprBybDmW4hcz3gYujhARhye+GoWKhEWyzD5sh4= github.com/pressly/goose/v3 v3.27.1 h1:6uEvcprBybDmW4hcz3gYujhARhye+GoWKhEWyzD5sh4=
github.com/pressly/goose/v3 v3.27.1/go.mod h1:maruOxsPnIG2yHHyo8UqKWXYKFcH7Q76csUV7+7KYoM= github.com/pressly/goose/v3 v3.27.1/go.mod h1:maruOxsPnIG2yHHyo8UqKWXYKFcH7Q76csUV7+7KYoM=
github.com/redis/go-redis/extra/rediscmd/v9 v9.18.0 h1:QY4nmPHLFAJjtT5O4OMUEOxP8WVaRNOFpcbmxT2NLZU=
github.com/redis/go-redis/extra/rediscmd/v9 v9.18.0/go.mod h1:WH8cY/0fT41Bsf341qzo8v4nx0GCE8FykAA23IVbVmo=
github.com/redis/go-redis/extra/redisotel/v9 v9.18.0 h1:2dKdoEYBJ0CZCLPiCdvvc7luz3DPwY6hKdzjL6m1eHE=
github.com/redis/go-redis/extra/redisotel/v9 v9.18.0/go.mod h1:WzkrVG9ro9BwCQD0eJOWn6AGL4Z1CleGflM45w1hu10=
github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs= github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs=
github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0= github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
+6 -4
View File
@@ -1,9 +1,11 @@
package rest package rest
type Init struct { type InitRequest struct {
Races []Race `json:"races" binding:"required,gte=10"` // List of the Races in the Game
Races []InitRace `json:"races" binding:"required,gte=10"`
} }
type Race struct { type InitRace struct {
Name string `json:"name" binding:"required,notblank"` // Name of the Race
RaceName string `json:"raceName" binding:"required,notblank"`
} }
+12 -1
View File
@@ -3,14 +3,25 @@ package rest
import "github.com/google/uuid" import "github.com/google/uuid"
type StateResponse struct { type StateResponse struct {
// Unique Game ID
ID uuid.UUID `json:"id"` ID uuid.UUID `json:"id"`
// Current Game Turn
Turn uint `json:"turn"` Turn uint `json:"turn"`
// Turn stage (for games that support stste modification)
Stage uint `json:"stage"` Stage uint `json:"stage"`
// List of Game's players
Players []PlayerState `json:"player"` Players []PlayerState `json:"player"`
} }
type PlayerState struct { type PlayerState struct {
// Unique Player ID within Game
ID uuid.UUID `json:"id"` ID uuid.UUID `json:"id"`
Name string `json:"name"` // Player's Race name
RaceName string `json:"raceName"`
// Number of planets owned by player
Planets uint `json:"planets"`
// Total population summ from all player's planets
Population float64 `json:"population"`
// True when Race is eliminated or left the game
Extinct bool `json:"extinct"` Extinct bool `json:"extinct"`
} }