entities/gate.go
package entities
import (
"fmt"
)
// Gate represents ticket gate in Station.
// Human must pass Gate to enter/leave Platform.
type Gate struct {
Base
Persistence
// Num represents how many Human can pass at the same time
Num int `gorm:"not null" json:"num"`
// Mobility represents time one Human pass Gate.
Mobility float64 `gorm:"not null" json:"mobility"`
// Occupied represents how many Gate are used by Human.
Occupied int `gorm:"not null" json:"occupied"`
InStation *Station `gorm:"-" json:"-"`
WithPlatform *Platform `gorm:"-" json:"-"`
out map[uint]*Step
in map[uint]*Step
StationID uint `gorm:"not null" json:"stid"`
PlatformID uint `gorm:"-" json:"pid"`
}
// NewGate creates instance
func (m *Model) NewGate(st *Station) *Gate {
g := &Gate{
Base: m.NewBase(GATE, st.O),
Persistence: NewPersistence(),
Num: m.conf.Gate.Num,
}
g.Init(m)
g.Resolve(st.O, st)
g.Marshal()
m.Add(g)
g.GenOutSteps()
g.GenInSteps()
return g
}
// B returns base information of this elements.
func (g *Gate) B() *Base {
return &g.Base
}
// P returns time information for database.
func (g *Gate) P() *Persistence {
return &g.Persistence
}
// Pos returns entities' position.
func (g *Gate) Pos() *Point {
if g.WithPlatform == nil {
return nil
}
return g.WithPlatform.Pos()
}
// GenOutSteps generates Steps from this Gate.
func (g *Gate) GenOutSteps() {
// skip G -> P
// G -> C
for _, c := range g.M.Companies {
g.M.NewStep(g, c)
}
}
// GenInSteps generates Steps to this Gate.
func (g *Gate) GenInSteps() {
// skip P -> G
// R -> G
for _, r := range g.M.Residences {
g.M.NewStep(r, g)
}
}
// Init creates map.
func (g *Gate) Init(m *Model) {
g.Base.Init(GATE, m)
g.out = make(map[uint]*Step)
g.in = make(map[uint]*Step)
}
// OutSteps returns where it can go to
func (g *Gate) OutSteps() map[uint]*Step {
return g.out
}
// InSteps returns where it comes from
func (g *Gate) InSteps() map[uint]*Step {
return g.in
}
// Resolve set reference
func (g *Gate) Resolve(args ...Entity) {
for _, raw := range args {
switch obj := raw.(type) {
case *Player:
g.O = obj
obj.Resolve(g)
case *Station:
g.InStation = obj
obj.Resolve(g)
case *Platform:
g.WithPlatform = obj
g.M.RootCluster.Add(g)
default:
panic(fmt.Errorf("invalid type: %T %+v", obj, obj))
}
}
g.Marshal()
}
// Marshal set id from reference
func (g *Gate) Marshal() {
if g.InStation != nil {
g.StationID = g.InStation.ID
}
if g.WithPlatform != nil {
g.PlatformID = g.WithPlatform.ID
}
}
// UnMarshal set reference from id.
func (g *Gate) UnMarshal() {
g.Resolve(
g.M.Find(PLAYER, g.OwnerID),
g.M.Find(STATION, g.StationID))
}
// CheckDelete check remain relation.
func (g *Gate) CheckDelete() error {
return nil
}
// BeforeDelete deletes related reference
func (g *Gate) BeforeDelete() {
g.O.UnResolve(g)
}
// Delete removes this entity with related ones.
func (g *Gate) Delete() {
for _, s := range g.out {
g.M.Delete(s)
}
for _, s := range g.in {
g.M.Delete(s)
}
g.M.Delete(g)
}
// String represents status
func (g *Gate) String() string {
g.Marshal()
ostr := ""
if g.O != nil {
ostr = fmt.Sprintf(":%s", g.O.Short())
}
ststr := ""
if g.InStation != nil {
ststr = fmt.Sprintf(":%s", g.InStation.Name)
}
posstr := ""
if g.Pos() != nil {
posstr = fmt.Sprintf(":%s", g.Pos())
}
return fmt.Sprintf("%s(%d):st=%d,p=%d,i=%d,o=%d%s%s%s", g.Type().Short(),
g.ID, g.StationID, g.PlatformID, len(g.in), len(g.out), posstr, ostr, ststr)
}