func (m *PositionFactory) GetPosition(id EID) (*Position, bool) {
	component, found := m.Position.Get(id)
	return component.(*Position), found
}
GetPosition returns the Position component for the given entity, and a bool for whether or not it exists
package akara
import (
	"fmt"
	"math"
	"math/rand"
	"testing"
	"time"
)
func between(min, max float64) float64 {
	range_ := max - min
	n := rand.Float64()
	return math.Round(min + (n * range_))
}
func Test_ExampleMovementSystem(t *testing.T) {
	sys := &MovementSystem{}
	systemTicks := 0
	sys.SetPostTickCallback(func() {
		systemTicks += 1
	})
	cfg := NewWorldConfig().With(sys)
	world := NewWorld(cfg)
	const numEntities = 4
	for idx := 0; idx < numEntities; idx++ {
		e := world.NewEntity()
		p := sys.AddPosition(e)
		v := sys.AddVelocity(e)
		p.X, p.Y = between(-10, 10), between(-10, 10)
		v.X, v.Y = between(-10, 10), between(-10, 10)
	}
	world.Update()
	numUpdates := 4
	loopsWaited := 0
	for systemTicks < numUpdates {
		if loopsWaited > 5 {
			t.Fail()
		}
		time.Sleep(10 * time.Millisecond)
		loopsWaited += 1
	}
}
func BenchmarkExampleMovementSystem(b *testing.B) {
	tests := []int{
		10,
		100,
		1000,
		10000,
		100000,
		1000000,
	}
	for _, n := range tests {
		name := fmt.Sprintf("%d entities", n)
		b.Run(name, func(b *testing.B) {
			Bench_ExampleMovementSystemN(n, b)
		})
	}
}
func Bench_ExampleMovementSystemN(numEntities int, b *testing.B) {
	sys := &MovementSystem{}
	sys.disableLog = true
	cfg := NewWorldConfig().With(sys)
	world := NewWorld(cfg)
	for idx := 0; idx < numEntities; idx++ {
		e := world.NewEntity()
		p := sys.AddPosition(e)
		v := sys.AddVelocity(e)
		p.X, p.Y = between(-10, 10), between(-10, 10)
		v.X, v.Y = between(-10, 10), between(-10, 10)
	}
	numUpdates := b.N
	for numUpdates > 0 {
		err := world.Update()
		if err != nil {
			b.Errorf("failed to update world: %s", err)
			b.Fail()
		}
		numUpdates--
	}
}
var _ System = &MovementSystem{}
type MovementSystem struct {
	BaseSystem
	PositionFactory
	VelocityFactory
	movableEntities *Subscription
	disableLog      bool
}
func (m *MovementSystem) Init(_ *World) {
	filter := m.NewComponentFilter().
		Require(
			&Position{},
			&Velocity{},
		).Build()
	m.movableEntities = m.AddSubscription(filter)
	positionID := m.RegisterComponent(&Position{})
	velocityID := m.RegisterComponent(&Velocity{})
	m.Position = m.GetComponentFactory(positionID)
	m.Velocity = m.GetComponentFactory(velocityID)
}
func (m *MovementSystem) Update() {
	entities := m.movableEntities.GetEntities()
	for entIdx := range entities {
		m.move(entities[entIdx])
	}
}
func (m *MovementSystem) move(id EID) {
	p, found := m.GetPosition(id)
	if !found {
		return
	}
	v, found := m.GetVelocity(id)
	if !found {
		return
	}
	s := float64(m.TimeDelta) / float64(time.Second)
	newX := p.X + (v.X * s)
	newY := p.Y + (v.Y * s)
	const strFmt = "p(%+.0f, %+.0f) + v(%+.0f, %+.0f)@%.0fs => p(%+.0f, %+.0f)\n"
	if !m.disableLog {
		fmt.Printf(strFmt, p.X, p.Y, v.X, v.Y, s, newX, newY)
	}
	p.X = newX
	p.Y = newY
}
var _ Component = &Velocity{}
type Velocity struct {
	X, Y float64
}
func (*Velocity) New() Component {
	return &Velocity{}
}
type VelocityFactory struct {
	Velocity *ComponentFactory
}
func (m *VelocityFactory) AddVelocity(id EID) *Velocity {
	return m.Velocity.Add(id).(*Velocity)
}
func (m *VelocityFactory) GetVelocity(id EID) (*Velocity, bool) {
	component, found := m.Velocity.Get(id)
	return component.(*Velocity), found
}
var _ Component = &Position{}
type Position struct {
	X, Y float64
}
func (*Position) New() Component {
	return &Position{}
}
type PositionFactory struct {
	Position *ComponentFactory
}
func (m *PositionFactory) AddPosition(id EID) *Position {
	return m.Position.Add(id).(*Position)
}