entity.go 5.7 KB

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