From b4591cabd40899acc9e793d624546914356b67d9 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Sun, 26 Apr 2026 21:12:51 +0200 Subject: [PATCH] game stats shows planes and population --- game/internal/controller/controller.go | 17 ++++++++++++++++- game/internal/model/game/state.go | 8 +++++--- game/internal/router/handler/handler.go | 4 +++- game/internal/router/handler/init.go | 4 ++-- game/internal/router/router_test.go | 8 ++++---- game/internal/router/status_test.go | 4 +++- game/internal/router/turn_test.go | 21 +++++++++++++++++++++ lobby/go.mod | 3 +++ lobby/go.sum | 4 ++++ pkg/model/rest/init.go | 10 ++++++---- pkg/model/rest/status.go | 23 +++++++++++++++++------ 11 files changed, 84 insertions(+), 22 deletions(-) diff --git a/game/internal/controller/controller.go b/game/internal/controller/controller.go index d8b872e..bbb84cd 100644 --- a/game/internal/controller/controller.go +++ b/game/internal/controller/controller.go @@ -152,10 +152,25 @@ func GameState(configure func(*Param)) (s game.State, err error) { 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 { r := &g.Race[i] 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 } diff --git a/game/internal/model/game/state.go b/game/internal/model/game/state.go index 4976b37..aaeba7e 100644 --- a/game/internal/model/game/state.go +++ b/game/internal/model/game/state.go @@ -10,7 +10,9 @@ type State struct { } type PlayerState struct { - ID uuid.UUID - Name string - Extinct bool + ID uuid.UUID + RaceName string + Planets uint + Population Float + Extinct bool } diff --git a/game/internal/router/handler/handler.go b/game/internal/router/handler/handler.go index 094ab3a..0454292 100644 --- a/game/internal/router/handler/handler.go +++ b/game/internal/router/handler/handler.go @@ -99,7 +99,9 @@ func stateResponse(s game.State) rest.StateResponse { } for i := range s.Players { 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 } return *result diff --git a/game/internal/router/handler/init.go b/game/internal/router/handler/init.go index d61b378..7abfe78 100644 --- a/game/internal/router/handler/init.go +++ b/game/internal/router/handler/init.go @@ -9,14 +9,14 @@ import ( ) func InitHandler(c *gin.Context, executor CommandExecutor) { - var init rest.Init + var init rest.InitRequest if errorResponse(c, c.ShouldBindJSON(&init)) { return } races := make([]string, len(init.Races)) for i := range init.Races { - races[i] = init.Races[i].Name + races[i] = init.Races[i].RaceName } s, err := executor.GenerateGame(races) diff --git a/game/internal/router/router_test.go b/game/internal/router/router_test.go index d0c63b5..4fac54c 100644 --- a/game/internal/router/router_test.go +++ b/game/internal/router/router_test.go @@ -68,12 +68,12 @@ func limitTestingRouter() *gin.Engine { return r } -func generateInitRequest(races int) rest.Init { - request := rest.Init{ - Races: make([]rest.Race, races), +func generateInitRequest(races int) rest.InitRequest { + request := rest.InitRequest{ + Races: make([]rest.InitRace, races), } for i := range request.Races { - request.Races[i] = rest.Race{Name: raceName(i)} + request.Races[i] = rest.InitRace{RaceName: raceName(i)} } return request } diff --git a/game/internal/router/status_test.go b/game/internal/router/status_test.go index c5ea005..bad6e0a 100644 --- a/game/internal/router/status_test.go +++ b/game/internal/router/status_test.go @@ -50,7 +50,9 @@ func TestGetStatus(t *testing.T) { assert.Len(t, stateResponse.Players, 10) for i := range stateResponse.Players { 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) } } diff --git a/game/internal/router/turn_test.go b/game/internal/router/turn_test.go index e5b7784..b961c7f 100644 --- a/game/internal/router/turn_test.go +++ b/game/internal/router/turn_test.go @@ -39,6 +39,13 @@ func TestGetTurn(t *testing.T) { assert.NotEqual(t, uuid.Nil, uuid.MustParse(initResponse.ID.String())) assert.Equal(t, uint(0), initResponse.Turn) 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 @@ -54,6 +61,13 @@ func TestGetTurn(t *testing.T) { assert.Equal(t, initResponse.ID, turnResponse.ID) assert.Equal(t, uint(1), turnResponse.Turn) 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 @@ -67,4 +81,11 @@ func TestGetTurn(t *testing.T) { assert.Equal(t, initResponse.ID, stateResponse.ID) assert.Equal(t, uint(1), stateResponse.Turn) 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) + } } diff --git a/lobby/go.mod b/lobby/go.mod index a72523e..adadb3a 100644 --- a/lobby/go.mod +++ b/lobby/go.mod @@ -4,6 +4,7 @@ go 1.26.1 require ( galaxy/postgres v0.0.0-00010101000000-000000000000 + galaxy/redisconn v0.0.0-00010101000000-000000000000 github.com/alicebob/miniredis/v2 v2.37.0 github.com/disciplinedware/go-confusables v0.1.1 github.com/getkin/kin-openapi v0.135.0 @@ -43,6 +44,8 @@ require ( github.com/lib/pq v1.10.9 // indirect github.com/mfridman/interpolate v0.0.2 // 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 go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.20.0 // indirect diff --git a/lobby/go.sum b/lobby/go.sum index e1a314e..452e7b9 100644 --- a/lobby/go.sum +++ b/lobby/go.sum @@ -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/pressly/goose/v3 v3.27.1 h1:6uEvcprBybDmW4hcz3gYujhARhye+GoWKhEWyzD5sh4= 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/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= diff --git a/pkg/model/rest/init.go b/pkg/model/rest/init.go index 3464553..1bbcf8e 100644 --- a/pkg/model/rest/init.go +++ b/pkg/model/rest/init.go @@ -1,9 +1,11 @@ package rest -type Init struct { - Races []Race `json:"races" binding:"required,gte=10"` +type InitRequest struct { + // List of the Races in the Game + Races []InitRace `json:"races" binding:"required,gte=10"` } -type Race struct { - Name string `json:"name" binding:"required,notblank"` +type InitRace struct { + // Name of the Race + RaceName string `json:"raceName" binding:"required,notblank"` } diff --git a/pkg/model/rest/status.go b/pkg/model/rest/status.go index c7f9f50..0d758bf 100644 --- a/pkg/model/rest/status.go +++ b/pkg/model/rest/status.go @@ -3,14 +3,25 @@ package rest import "github.com/google/uuid" type StateResponse struct { - ID uuid.UUID `json:"id"` - Turn uint `json:"turn"` - Stage uint `json:"stage"` + // Unique Game ID + ID uuid.UUID `json:"id"` + // Current Game Turn + Turn uint `json:"turn"` + // Turn stage (for games that support stste modification) + Stage uint `json:"stage"` + // List of Game's players Players []PlayerState `json:"player"` } type PlayerState struct { - ID uuid.UUID `json:"id"` - Name string `json:"name"` - Extinct bool `json:"extinct"` + // Unique Player ID within Game + ID uuid.UUID `json:"id"` + // 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"` }