You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
5.7 KiB

  1. package models
  2. import (
  3. "errors"
  4. "time"
  5. "github.com/arnaucube/gogame/database"
  6. "gopkg.in/mgo.v2/bson"
  7. )
  8. type Resources struct {
  9. Metal int64
  10. Crystal int64
  11. Deuterium int64
  12. Energy int64
  13. }
  14. // UserDb is the data in DB
  15. type UserDb struct {
  16. Id bson.ObjectId `json:"id" bson:"_id,omitempty"`
  17. Name string
  18. Password string
  19. Email string
  20. LastUpdated time.Time
  21. Resources Resources
  22. Planets []bson.ObjectId
  23. }
  24. // User is the data in memory, after getting it from DB
  25. type User struct {
  26. Id bson.ObjectId `json:"id" bson:"_id,omitempty"`
  27. Name string
  28. LastUpdated time.Time
  29. db *database.Db
  30. Resources Resources
  31. Planets []bson.ObjectId
  32. }
  33. func NewUser(db *database.Db, name, password, email string) (*User, error) {
  34. newUser := UserDb{
  35. Id: bson.NewObjectId(),
  36. Name: name,
  37. Password: password,
  38. Email: email,
  39. LastUpdated: time.Now(),
  40. Resources: Resources{
  41. Metal: 500,
  42. Crystal: 500,
  43. Deuterium: 500,
  44. Energy: 500,
  45. },
  46. }
  47. err := db.Users.Insert(newUser)
  48. if err != nil {
  49. return nil, err
  50. }
  51. user := UserDbToUser(db, newUser)
  52. return user, nil
  53. }
  54. func UserDbToUser(db *database.Db, u UserDb) *User {
  55. return &User{
  56. Id: u.Id,
  57. Name: u.Name,
  58. LastUpdated: u.LastUpdated,
  59. db: db,
  60. Resources: u.Resources,
  61. Planets: u.Planets,
  62. }
  63. }
  64. func (u *User) StoreInDb() error {
  65. err := u.db.Users.Update(bson.M{"_id": u.Id}, bson.M{"$set": bson.M{
  66. "lastupdated": time.Now(),
  67. "resources": u.Resources,
  68. "planets": u.Planets,
  69. }})
  70. return err
  71. }
  72. func (u *User) GetFromDb() error {
  73. var userDb UserDb
  74. err := u.db.Users.Find(bson.M{"_id": u.Id}).One(&userDb)
  75. if err != nil {
  76. return err
  77. }
  78. u = UserDbToUser(u.db, userDb)
  79. return nil
  80. }
  81. func (u *User) GetPlanets() ([]Planet, error) {
  82. var planets []Planet
  83. err := u.db.Planets.Find(bson.M{"ownerid": u.Id}).All(&planets)
  84. if err != nil {
  85. return planets, err
  86. }
  87. return planets, nil
  88. }
  89. // GetResources updates the values of resources and returns the value, also updates the user.Resources
  90. // Resource types: metal, crystal, deuterium, energy
  91. func (u *User) GetResources() (*Resources, error) {
  92. // get current values
  93. err := u.GetFromDb()
  94. if err != nil {
  95. return nil, err
  96. }
  97. // calculate Delta time = currentTime - u.LastUpdated
  98. delta := time.Since(u.LastUpdated).Seconds()
  99. // get planets
  100. planets, err := u.GetPlanets()
  101. if err != nil {
  102. return nil, err
  103. }
  104. // get Resource-Plant level in each planet
  105. // and calculate growth = ResourcePlant.Level for each planet
  106. var metalGrowth, crystalGrowth, deuteriumGrowth, energyGrowth int64
  107. for _, planet := range planets {
  108. metalGrowth = metalGrowth + MetalGrowth(planet.Buildings["metalmine"], int64(delta))
  109. crystalGrowth = crystalGrowth + MetalGrowth(planet.Buildings["crystalmine"], int64(delta))
  110. deuteriumGrowth = deuteriumGrowth + MetalGrowth(planet.Buildings["deuteriummine"], int64(delta))
  111. energyGrowth = energyGrowth + MetalGrowth(planet.Buildings["energymine"], int64(delta))
  112. }
  113. // calculate newAmount = oldAmount + growth
  114. u.Resources.Metal = u.Resources.Metal + metalGrowth
  115. u.Resources.Crystal = u.Resources.Crystal + crystalGrowth
  116. u.Resources.Deuterium = u.Resources.Deuterium + deuteriumGrowth
  117. u.Resources.Energy = u.Resources.Energy + energyGrowth
  118. // store new amount to user db
  119. err = u.StoreInDb()
  120. if err != nil {
  121. return nil, err
  122. }
  123. // return user
  124. return &u.Resources, nil
  125. }
  126. // SpendResources checks if user has enough resources, then substracts the resources, and updates the amounts in the database
  127. func (u *User) SpendResources(r Resources) error {
  128. err := u.GetFromDb()
  129. if err != nil {
  130. return err
  131. }
  132. if u.Resources.Metal < r.Metal {
  133. return errors.New("not enough metal resources")
  134. }
  135. if u.Resources.Crystal < r.Crystal {
  136. return errors.New("not enough crystal resources")
  137. }
  138. if u.Resources.Deuterium < r.Deuterium {
  139. return errors.New("not enough deuterium resources")
  140. }
  141. if u.Resources.Energy < r.Energy {
  142. return errors.New("not enough energy resources")
  143. }
  144. u.Resources.Metal = u.Resources.Metal - r.Metal
  145. u.Resources.Crystal = u.Resources.Crystal - r.Crystal
  146. u.Resources.Deuterium = u.Resources.Deuterium - r.Deuterium
  147. u.Resources.Energy = u.Resources.Energy - r.Energy
  148. err = u.StoreInDb()
  149. if err != nil {
  150. return err
  151. }
  152. return nil
  153. }
  154. func (u *User) GetBuildingCost(planet Planet, building string) (Resources, error) {
  155. switch building {
  156. case "metalmine":
  157. return MetalMineCost(planet.Buildings["metalmine"] + 1), nil
  158. case "crystalmine":
  159. return CrystalMineCost(planet.Buildings["crystalmine"] + 1), nil
  160. case "deuteriummine":
  161. return DeuteriumMineCost(planet.Buildings["deuteriummine"] + 1), nil
  162. case "energymine":
  163. return EnergyMineCost(planet.Buildings["energymine"] + 1), nil
  164. case "fusionreactor":
  165. return FussionReactorCost(planet.Buildings["fusionreactor"] + 1), nil
  166. case "roboticsfactory":
  167. return RoboticsFactoryCost(planet.Buildings["roboticsfactory"] + 1), nil
  168. case "shipyard":
  169. return ShipyardCost(planet.Buildings["shipyard"] + 1), nil
  170. case "metalstorage":
  171. return MetalStorageCost(planet.Buildings["metalstorage"] + 1), nil
  172. case "crystalstorage":
  173. return CrystalStorageCost(planet.Buildings["crystalstorage"] + 1), nil
  174. case "deuteriumstorage":
  175. return DeuteriumStorageCost(planet.Buildings["deuteriumstorage"] + 1), nil
  176. case "ressearchlab":
  177. return RessearchLabCost(planet.Buildings["ressearchlab"] + 1), nil
  178. case "alliancedepot":
  179. return AllianceDepotCost(planet.Buildings["alliancedepot"] + 1), nil
  180. case "missilesilo":
  181. return MissileSiloCost(planet.Buildings["missilesilo"] + 1), nil
  182. case "spacedock":
  183. return SpaceDockCost(planet.Buildings["spacedock"] + 1), nil
  184. default:
  185. return Resources{}, errors.New("building not found")
  186. }
  187. }