entity.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package world
  2. import "strings"
  3. import "os"
  4. import "sort"
  5. import "encoding/xml"
  6. import "github.com/beoran/woe/sitef"
  7. // Anything inside the WOE World can be identified by a unique short string
  8. // description, the Label
  9. type Labeled interface {
  10. Label() string // Returns a unique label of the thing.
  11. }
  12. type Typed interface {
  13. Type() string // Returns a string description of the type of the thing.
  14. }
  15. // An entity is anything that can exist in a World
  16. type Entity struct {
  17. ID string `xml:"id,attr"`
  18. Name string `xml:"name,attr"`
  19. Short string `xml:"short,attr"`
  20. Long string
  21. Aliases []string
  22. // Privilege level needed to use/interact with/enter/... this Entity
  23. Privilege Privilege
  24. }
  25. func (me * Entity) InitKind(kind string, name string,
  26. privilege Privilege) (* Entity) {
  27. if me == nil {
  28. return me
  29. }
  30. me.ID = kind + "_" + strings.ToLower(name)
  31. me.Name = name
  32. me.Short = name
  33. me.Long = name
  34. me.Privilege= privilege
  35. return me
  36. }
  37. // Devious polymorphism for Entities...
  38. type Entitylike interface {
  39. AsEntity() * Entity
  40. }
  41. // A little trick to need less setters and getters
  42. func (me * Entity) AsEntity() (*Entity) {
  43. return me
  44. }
  45. func (me Entity) Label() string {
  46. return string(me.ID)
  47. }
  48. type EntitySlice []Entitylike
  49. type EntityMap map[string]Entitylike
  50. type EntityLookup struct {
  51. slice EntitySlice
  52. table EntityMap
  53. }
  54. // By is the type of a "less" function that defines the ordering of its Planet arguments.
  55. type EntityLikeBy func(p1, p2 Entitylike) bool
  56. // planetSorter joins a By function and a slice of Planets to be sorted.
  57. type EntityLikeSorter struct {
  58. Entities EntitySlice
  59. By EntityLikeBy
  60. }
  61. func (me EntitySlice) By(compare func (p1, p2 Entitylike) bool) *EntityLikeSorter {
  62. return &EntityLikeSorter { me, EntityLikeBy(compare) };
  63. }
  64. // Len is part of sort.Interface.
  65. func (s * EntityLikeSorter) Len() int {
  66. return len(s.Entities)
  67. }
  68. // Swap is part of sort.Interface.
  69. func (s *EntityLikeSorter) Swap(i, j int) {
  70. s.Entities[i], s.Entities[j] = s.Entities[j], s.Entities[i]
  71. }
  72. // Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
  73. func (s *EntityLikeSorter) Less(i, j int) bool {
  74. return s.By(s.Entities[i], s.Entities[j])
  75. }
  76. func (me * EntityLikeSorter) Sort() {
  77. sort.Sort(me)
  78. }
  79. // Sort is a method on the function type, By, that sorts the argument slice according to the function.
  80. func (by EntityLikeBy) Sort(entities EntitySlice) {
  81. ps := &EntityLikeSorter{
  82. Entities: entities,
  83. By: by, // The Sort method's receiver is the function (closure) that defines the sort order.
  84. }
  85. sort.Sort(ps)
  86. }
  87. func (me EntityLookup) Get(index int) Entitylike {
  88. return me.slice[index]
  89. }
  90. func (me EntityLookup) Len() int {
  91. return len(me.table)
  92. }
  93. func (me * EntityLookup) Add(ent Entitylike) int {
  94. me.slice = append(me.slice, ent)
  95. me.slice.By(func (e1, e2 Entitylike) bool {
  96. return (e1.AsEntity().Label() < e2.AsEntity().Label())
  97. }).Sort()
  98. res := len(me.slice) - 1
  99. if me.table == nil {
  100. me.table = make(EntityMap)
  101. }
  102. me.table[ent.AsEntity().Label()] = ent
  103. return res
  104. }
  105. func (me EntityLookup) Lookup(id string) (Entitylike) {
  106. res, ok := me.table[id]
  107. if !ok {
  108. return nil
  109. }
  110. return res
  111. }
  112. func (me EntityLookup) Remove(ent Entitylike) bool {
  113. key := ent.AsEntity().Label()
  114. delete(me.table, key)
  115. return true
  116. }
  117. type EntityLookupEachFunc func (id string, ent Entitylike, args...interface{}) Entitylike
  118. func (me EntityLookup) Each(lambda EntityLookupEachFunc, args...interface{}) Entitylike {
  119. for k, v := range (me.table) {
  120. res := lambda(k, v, args...)
  121. if res != nil {
  122. return res
  123. }
  124. }
  125. return nil
  126. }
  127. type EntityList interface {
  128. Get(int) Entitylike
  129. Len() int
  130. Add(Entitylike) int
  131. Lookup(string) (Entitylike)
  132. Remove(Entitylike) bool
  133. }
  134. // Interface
  135. type Savable interface {
  136. Labeled
  137. Typed
  138. }
  139. type Loadable interface {
  140. Typed
  141. }
  142. func SaveSavable(dirname string, savable Savable) (err error) {
  143. path := SavePathFor(dirname, savable.Type(), savable.Label())
  144. file, err := os.Create(path)
  145. if err != nil {
  146. return err
  147. }
  148. enc := xml.NewEncoder(file)
  149. enc.Indent(" ", " ")
  150. return enc.Encode(savable)
  151. }
  152. func LoadLoadable(dirname string, nameid string, result Loadable) (Loadable) {
  153. path := SavePathFor(dirname, result.Type(), nameid)
  154. file, err := os.Open(path)
  155. if err != nil {
  156. return nil
  157. }
  158. dec := xml.NewDecoder(file)
  159. err = dec.Decode(result)
  160. if err != nil { return nil }
  161. return result
  162. }
  163. // A list of Identifier items mapped to their ID's
  164. type LabeledLister interface {
  165. Get(string) Labeled
  166. Put(Labeled)
  167. Size() int
  168. Index(int) Labeled
  169. PutIndex(int)
  170. }
  171. type LabeledList struct {
  172. byList []Labeled
  173. byLabel map[string] Labeled
  174. }
  175. func NewLabeledList() * LabeledList {
  176. byname := make(map[string] Labeled)
  177. return &LabeledList{nil, byname}
  178. }
  179. func (me * LabeledList) Get(id string) Labeled {
  180. val, ok := me.byLabel[id]
  181. if !ok { return nil }
  182. return val
  183. }
  184. func (me * LabeledList) Index(index int) Labeled {
  185. if index < 0 { return nil }
  186. if index > len(me.byList) { return nil }
  187. val := me.byList[index]
  188. return val
  189. }
  190. // Save an entity to a sitef record.
  191. func (me * Entity) SaveSitef(rec sitef.Record) (err error) {
  192. rec["id"] = string(me.ID)
  193. rec["name"] = me.Name
  194. rec["short"] = me.Short
  195. rec["long"] = me.Long
  196. return nil
  197. }
  198. // Load an entity from a sitef record.
  199. func (me * Entity) LoadSitef(rec sitef.Record) (err error) {
  200. me.ID = rec["id"]
  201. me.Name = rec["name"]
  202. me.Short = rec["short"]
  203. me.Long = rec["long"]
  204. return nil
  205. }