diff --git a/astro/services/Pool.go b/astro/services/Pool.go
index 73eeaf08579c72de36b3012ed85a9be245b82a40..a625b9b9c8a408d726899d602f0d192ef9b9490a 100644
--- a/astro/services/Pool.go
+++ b/astro/services/Pool.go
@@ -6,8 +6,18 @@ type Pool struct {
 	PoolID      uint8 // 255 pools max
 	PoolState   State
 	PoolMaxSize uint16
-	PoolPlayers []Player
-	PoolReferee Referee
+	PoolSize    uint16
+	PoolPlayers map[uint16]*Player
+	PoolReferee *Referee
+}
+
+type PoolStage struct {
+	PoolStageID              uint8
+	PoolStageSize            uint16
+	PoolPlayers              map[uint16]*Player
+	PoolStagePools           map[uint8]*Pool
+	PoolStageState           State
+	PoolEnteringPlayerNumber uint16
 }
 
 func (p Pool) String() string {
@@ -22,60 +32,261 @@ func (p Pool) String() string {
 	return s
 }
 
-func CreateStage(poolID uint8, poolMaxSize uint16) Pool {
-	var p Pool
+func CreatePoolStage(poolStageID uint8, enteringPlayerNumber uint16, leavingPlayerNumber uint16) PoolStage {
+	var s PoolStage
 
-	p.PoolID = poolID
-	p.PoolState = IDLE
-	p.PoolMaxSize = poolMaxSize
-	p.PoolPlayers = make([]Player, poolMaxSize)
-	p.PoolReferee = Referee{}
+	s.PoolStageID = poolStageID
+	s.PoolEnteringPlayerNumber = enteringPlayerNumber
+	s.PoolPlayers = make(map[uint16]*Player)
+	s.PoolStagePools = make(map[uint8]*Pool)
+	s.PoolStageState = IDLE
+	s.PoolStageSize = 0
 
-	return p
+	return s
 }
 
-func (p Pool) PlayerPosition(player Player) uint16 {
-	for i, poolPlayer := range p.PoolPlayers {
-		if poolPlayer.PlayerID == player.PlayerID {
-			return uint16(i)
+// From interface
+func (p *PoolStage) PlayerPosition(player *Player) uint16 {
+	for _, pool := range p.PoolStagePools {
+		if pool.PlayerPosition(player) != math.MaxInt16 {
+			return pool.PlayerPosition(player)
 		}
 	}
 
 	return math.MaxInt16
 }
 
-func (p *Pool) AddPlayer(player Player) bool {
-	if p.PoolState != IDLE {
+// From interface
+func (p *PoolStage) AddPlayer(player *Player) bool {
+	if p.PoolStageState != REGISTERING {
 		return false
 	}
 
-	if len(p.PoolPlayers) >= int(p.PoolMaxSize) {
+	if p.PlayerPosition(player) != math.MaxInt16 {
+		return false
+	}
+
+	for _, pool := range p.PoolStagePools {
+		if pool.AddPlayer(player) {
+			p.PoolPlayers[player.PlayerID] = player
+			p.PoolStageSize++
+
+			pool.PoolSize++
+			return true
+		}
+	}
+
+	// Add pool
+	pool := &Pool{
+		PoolID:      uint8(len(p.PoolStagePools)),
+		PoolState:   REGISTERING,
+		PoolMaxSize: 7,
+		PoolSize:    0,
+		PoolPlayers: make(map[uint16]*Player),
+		PoolReferee: nil,
+	}
+
+	pool.AddPlayer(player)
+
+	p.AddPool(pool)
+	p.PoolPlayers[player.PlayerID] = player
+
+	return true
+}
+
+// From interface
+func (p *PoolStage) RemovePlayer(player *Player) bool {
+	if p.PoolStageState != REGISTERING {
 		return false
 	}
 
 	if p.PlayerPosition(player) == math.MaxInt16 {
-		p.PoolPlayers = append(p.PoolPlayers, player)
-		return true
+		return false
+	}
+
+	for _, pool := range p.PoolStagePools {
+		if pool.RemovePlayer(player) {
+			delete(p.PoolPlayers, player.PlayerID)
+			p.PoolStageSize--
+
+			pool.PoolSize--
+
+			if pool.PoolSize == 0 {
+				p.RemovePool(pool)
+			}
+
+			return true
+		}
 	}
 
 	return false
 }
 
-func (p *Pool) RemovePlayer(player Player) bool {
-	if p.PoolState != IDLE {
+// From interface
+func (p *PoolStage) GetID() uint8 {
+	return p.PoolStageID
+}
+
+// From interface
+func (p *PoolStage) GetState() State {
+	return p.PoolStageState
+}
+
+// From interface
+func (p *PoolStage) GetPlayers() []*Player {
+	players := []*Player{}
+
+	for _, player := range p.PoolPlayers {
+		players = append(players, player)
+	}
+
+	return players
+}
+
+// From interface
+func (p *PoolStage) Register() bool {
+	if p.PoolStageState != IDLE {
 		return false
 	}
 
-	pos := p.PlayerPosition(player)
+	p.PoolStageState = REGISTERING
+
+	return true
+}
+
+// From interface
+func (p *PoolStage) Start() bool {
+	if p.PoolStageState != REGISTERING {
+		return false
+	}
 
-	if pos != math.MaxInt16 {
-		p.PoolPlayers = append(p.PoolPlayers[:pos], p.PoolPlayers[pos+1:]...)
-		return true
+	if p.PoolStageSize < p.PoolEnteringPlayerNumber {
+		return false
 	}
 
+	p.PoolStageState = STARTED
+
+	return true
+}
+
+// From interface
+func (p *PoolStage) End() bool {
+	if p.PoolStageState != STARTED {
+		return false
+	}
+
+	p.PoolStageState = FINISHED
+
+	return true
+}
+
+// From interface
+func (p *PoolStage) Lock() bool {
+	if p.PoolStageState != FINISHED {
+		return false
+	}
+
+	p.PoolStageState = LOCKED
+
+	return true
+}
+
+// From interface
+func (p *PoolStage) Build() bool {
+	// TODO: Implement
 	return false
 }
 
-func (p *Pool) SetReferee(referee Referee) {
+func (p *PoolStage) AddPool(pool *Pool) bool {
+	if p.PoolStageState != REGISTERING {
+		return false
+	}
+
+	if pool == nil {
+		return false
+	}
+
+	p.PoolStagePools[pool.PoolID] = pool
+
+	return true
+}
+
+func (p *PoolStage) RemovePool(pool *Pool) bool {
+	if p.PoolStageState != REGISTERING {
+		return false
+	}
+
+	if pool == nil {
+		return false
+	}
+
+	if pool.PoolSize > 0 {
+		return false
+	}
+
+	delete(p.PoolStagePools, pool.PoolID)
+
+	return true
+}
+
+func (p *PoolStage) GetPool(poolID uint8) *Pool {
+	pool, ok := p.PoolStagePools[poolID]
+	if ok {
+		return pool
+	}
+
+	return nil
+}
+
+// ------------------------------ Pool ------------------------------
+func (p Pool) PlayerPosition(player *Player) uint16 {
+	_, ok := p.PoolPlayers[player.PlayerID]
+	if ok {
+		return p.PoolPlayers[player.PlayerID].PlayerID
+	}
+
+	return math.MaxInt16
+}
+
+func (p *Pool) AddPlayer(player *Player) bool {
+	if p.PoolState != REGISTERING {
+		return false
+	}
+
+	if p.PoolSize >= p.PoolMaxSize {
+		return false
+	}
+
+	if p.PlayerPosition(player) != math.MaxInt16 {
+		return false
+	}
+
+	p.PoolPlayers[p.PoolSize] = player
+	p.PoolSize++
+
+	return true
+}
+
+func (p *Pool) RemovePlayer(player *Player) bool {
+	if p.PoolState != REGISTERING {
+		return false
+	}
+
+	if p.PlayerPosition(player) == math.MaxInt16 {
+		return false
+	}
+
+	delete(p.PoolPlayers, player.PlayerID)
+
+	return true
+}
+
+func (p *Pool) SetReferee(referee *Referee) bool {
+	if p.PoolState != REGISTERING {
+		return false
+	}
+
 	p.PoolReferee = referee
+
+	return true
 }
diff --git a/astro/services/Seeding.go b/astro/services/Seeding.go
new file mode 100644
index 0000000000000000000000000000000000000000..d1b7815f0366508dab29f1805f78da8f1a3ef75f
--- /dev/null
+++ b/astro/services/Seeding.go
@@ -0,0 +1,163 @@
+package services
+
+// Seeding : Seeding details
+type Seeding struct {
+	SeedingPosition uint16
+	SeedingPlayer   *Player
+}
+
+type SeedingStage struct {
+	SeedingStageID              uint8
+	SeedingSize                 uint16
+	SeedingSeedings             map[uint16]*Seeding
+	SeedingState                State
+	SeedingEnteringPlayerNumber uint16
+}
+
+func (s *SeedingStage) String() string {
+	var str string
+
+	str = string(s.SeedingStageID) + " - " + s.SeedingState.String()
+
+	for _, seeding := range s.SeedingSeedings {
+		str = str + "\n" + seeding.SeedingPlayer.String()
+	}
+
+	return str
+}
+
+func CreateSeedingStage(seedingStageID uint8, enteringPlayerNumber uint16, leavingPlayerNumber uint16) SeedingStage {
+	var s SeedingStage
+
+	s.SeedingStageID = seedingStageID
+	s.SeedingEnteringPlayerNumber = enteringPlayerNumber
+	s.SeedingSeedings = make(map[uint16]*Seeding)
+	s.SeedingState = IDLE
+	s.SeedingSize = 0
+
+	return s
+}
+
+// From interface
+func (s *SeedingStage) PlayerPosition(player Player) uint16 {
+	return s.SeedingSeedings[player.PlayerID].SeedingPosition
+}
+
+// From interface
+func (s *SeedingStage) AddPlayer(player Player) bool {
+	if s.SeedingState != REGISTERING {
+		return false
+	}
+
+	if s.SeedingSeedings[player.PlayerID] != nil {
+		return false
+	}
+
+	s.SeedingSeedings[player.PlayerID] = &Seeding{
+		SeedingPosition: s.SeedingSize,
+		SeedingPlayer:   &player,
+	}
+
+	s.SeedingSize++
+
+	return true
+}
+
+// From interface
+func (s *SeedingStage) RemovePlayer(player Player) bool {
+	if s.SeedingState != REGISTERING {
+		return false
+	}
+
+	if s.SeedingSeedings[player.PlayerID] == nil {
+		return false
+	}
+
+	delete(s.SeedingSeedings, player.PlayerID)
+
+	s.SeedingSize--
+
+	return true
+}
+
+// From interface
+func (s *SeedingStage) GetID() uint8 {
+	return s.SeedingStageID
+}
+
+// From interface
+func (s *SeedingStage) GetState() State {
+	return s.SeedingState
+}
+
+// From interface
+func (s *SeedingStage) GetPlayers() []Player {
+	players := []Player{}
+
+	for _, seeding := range s.SeedingSeedings {
+		players = append(players, *seeding.SeedingPlayer)
+	}
+
+	return players
+}
+
+// From interface
+func (s *SeedingStage) Register() bool {
+	if s.SeedingState != IDLE {
+		return false
+	}
+
+	s.SeedingState = REGISTERING
+
+	return true
+}
+
+// From interface
+func (s *SeedingStage) Start() bool {
+	if s.SeedingState != REGISTERING {
+		return false
+	}
+
+	if s.SeedingSize != s.SeedingEnteringPlayerNumber {
+		return false
+	}
+
+	s.SeedingState = STARTED
+
+	return true
+}
+
+// From interface
+func (s *SeedingStage) End() bool {
+	if s.SeedingState != STARTED {
+		return false
+	}
+
+	s.SeedingState = FINISHED
+
+	return true
+}
+
+// From interface
+func (s *SeedingStage) Lock() bool {
+	if s.SeedingState != FINISHED {
+		return false
+	}
+
+	s.SeedingState = LOCKED
+
+	return true
+}
+
+// From interface
+func (s *SeedingStage) Build() bool {
+	if s.SeedingState != REGISTERING {
+		return false
+	}
+
+	if s.SeedingSize != s.SeedingEnteringPlayerNumber {
+		return false
+	}
+
+	return true
+}
diff --git a/astro/services/Stage.go b/astro/services/Stage.go
index 13601244637b9ac12b65115f136b3ffcef48fd93..0be18200824ee8acee6dc19080f1e39643442fd4 100644
--- a/astro/services/Stage.go
+++ b/astro/services/Stage.go
@@ -2,9 +2,15 @@ package services
 
 // Stage : Stage details
 type Stage interface {
-	CreateStage(stageID uint8, stageMaxSize uint16) Stage
 	PlayerPosition(player Player) uint16
 	AddPlayer(player Player) bool
 	RemovePlayer(player Player) bool
 	GetID() uint8
+	GetState() State
+	GetPlayers() []Player
+	Register() bool
+	Start() bool
+	End() bool
+	Lock() bool
+	Build() bool
 }
diff --git a/astro/services/Util.go b/astro/services/Util.go
index b357fed01a2e3ac93a318a74d6dd006b4608f1f6..91d12d8408f9e12c529cc84689376e4b5ebf225f 100644
--- a/astro/services/Util.go
+++ b/astro/services/Util.go
@@ -107,7 +107,8 @@ const (
 	REGISTERING State = iota // 0
 	STARTED                  // 1
 	FINISHED                 // 2
-	IDLE                     // 3
+	LOCKED                   // 3
+	IDLE                     // 4
 )
 
 func (s State) String() string {
@@ -118,6 +119,8 @@ func (s State) String() string {
 		return "Started"
 	case FINISHED:
 		return "Finished"
+	case LOCKED:
+		return "Locked"
 	case IDLE:
 		return "Idle"
 	default: