package models
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/arnaucube/gogame/database"
|
|
"gopkg.in/mgo.v2/bson"
|
|
)
|
|
|
|
type Resources struct {
|
|
Metal int64
|
|
Crystal int64
|
|
Deuterium int64
|
|
Energy int64
|
|
}
|
|
|
|
// UserDb is the data in DB
|
|
type UserDb struct {
|
|
Id bson.ObjectId `json:"id" bson:"_id,omitempty"`
|
|
Name string
|
|
Password string
|
|
Email string
|
|
LastUpdated time.Time
|
|
Resources Resources
|
|
Planets []bson.ObjectId
|
|
}
|
|
|
|
// User is the data in memory, after getting it from DB
|
|
type User struct {
|
|
Id bson.ObjectId `json:"id" bson:"_id,omitempty"`
|
|
Name string
|
|
LastUpdated time.Time
|
|
db *database.Db
|
|
Resources Resources
|
|
}
|
|
|
|
func NewUser(db *database.Db, name, password, email string) (*User, error) {
|
|
newUser := UserDb{
|
|
Id: bson.NewObjectId(),
|
|
Name: name,
|
|
Password: password,
|
|
Email: email,
|
|
LastUpdated: time.Now(),
|
|
Resources: Resources{
|
|
Metal: 500,
|
|
Crystal: 500,
|
|
Deuterium: 500,
|
|
Energy: 500,
|
|
},
|
|
}
|
|
err := db.Users.Insert(newUser)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
user := UserDbToUser(db, newUser)
|
|
return user, nil
|
|
}
|
|
|
|
func UserDbToUser(db *database.Db, u UserDb) *User {
|
|
return &User{
|
|
Id: u.Id,
|
|
Name: u.Name,
|
|
LastUpdated: u.LastUpdated,
|
|
db: db,
|
|
Resources: u.Resources,
|
|
}
|
|
}
|
|
|
|
func (u *User) StoreInDb() error {
|
|
userDb := UserDb{
|
|
Id: u.Id,
|
|
Name: u.Name,
|
|
LastUpdated: time.Now(),
|
|
Resources: u.Resources,
|
|
}
|
|
err := u.db.Users.Update(bson.M{"_id": u.Id}, userDb)
|
|
return err
|
|
|
|
}
|
|
|
|
func (u *User) GetFromDb() error {
|
|
var userDb UserDb
|
|
err := u.db.Users.Find(bson.M{"_id": u.Id}).One(&userDb)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
u = UserDbToUser(u.db, userDb)
|
|
return nil
|
|
}
|
|
|
|
func (u *User) GetPlanets() ([]Planet, error) {
|
|
var planets []Planet
|
|
err := u.db.Planets.Find(bson.M{"ownerid": u.Id}).All(&planets)
|
|
if err != nil {
|
|
return planets, err
|
|
}
|
|
return planets, nil
|
|
}
|
|
|
|
// GetResources updates the values of resources and returns the value, also updates the user.Resources
|
|
// Resource types: metal, crystal, deuterium, energy
|
|
func (u *User) GetResources() (*Resources, error) {
|
|
// get current values
|
|
err := u.GetFromDb()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// calculate Delta time = currentTime - u.LastUpdated
|
|
delta := time.Since(u.LastUpdated).Seconds()
|
|
|
|
// get planets
|
|
planets, err := u.GetPlanets()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// get Resource-Plant level in each planet
|
|
// and calculate growth = ResourcePlant.Level for each planet
|
|
var metalGrowth, crystalGrowth, deuteriumGrowth, energyGrowth int64
|
|
for _, planet := range planets {
|
|
metalGrowth = metalGrowth + MetalGrowth(planet.Buildings["metalmine"], int64(delta))
|
|
crystalGrowth = crystalGrowth + MetalGrowth(planet.Buildings["crystalmine"], int64(delta))
|
|
deuteriumGrowth = deuteriumGrowth + MetalGrowth(planet.Buildings["deuteriummine"], int64(delta))
|
|
energyGrowth = energyGrowth + MetalGrowth(planet.Buildings["energymine"], int64(delta))
|
|
}
|
|
// calculate newAmount = oldAmount + growth
|
|
u.Resources.Metal = u.Resources.Metal + metalGrowth
|
|
u.Resources.Crystal = u.Resources.Crystal + crystalGrowth
|
|
u.Resources.Deuterium = u.Resources.Deuterium + deuteriumGrowth
|
|
u.Resources.Energy = u.Resources.Energy + energyGrowth
|
|
|
|
// store new amount to user db
|
|
err = u.StoreInDb()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// return user
|
|
return &u.Resources, nil
|
|
}
|
|
|
|
// SpendResources checks if user has enough resources, then substracts the resources, and updates the amounts in the database
|
|
func (u *User) SpendResources(r Resources) error {
|
|
err := u.GetFromDb()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if u.Resources.Metal < r.Metal {
|
|
return errors.New("not enough metal resources")
|
|
}
|
|
if u.Resources.Crystal < r.Crystal {
|
|
return errors.New("not enough crystal resources")
|
|
}
|
|
if u.Resources.Deuterium < r.Deuterium {
|
|
return errors.New("not enough deuterium resources")
|
|
}
|
|
if u.Resources.Energy < r.Energy {
|
|
return errors.New("not enough energy resources")
|
|
}
|
|
|
|
u.Resources.Metal = u.Resources.Metal - r.Metal
|
|
u.Resources.Crystal = u.Resources.Crystal - r.Crystal
|
|
u.Resources.Deuterium = u.Resources.Deuterium - r.Deuterium
|
|
u.Resources.Energy = u.Resources.Energy - r.Energy
|
|
|
|
err = u.StoreInDb()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (u *User) GetBuildingCost(planet Planet, building string) (Resources, error) {
|
|
switch building {
|
|
case "metalmine":
|
|
return MetalMineCost(planet.Buildings["metalmine"] + 1), nil
|
|
case "crystalmine":
|
|
return CrystalMineCost(planet.Buildings["crystalmine"] + 1), nil
|
|
case "deuteriummine":
|
|
return DeuteriumMineCost(planet.Buildings["deuteriummine"] + 1), nil
|
|
case "energymine":
|
|
return EnergyMineCost(planet.Buildings["energymine"] + 1), nil
|
|
case "ressearchlab":
|
|
return RessearchLabCost(planet.Buildings["ressearchlab"] + 1), nil
|
|
default:
|
|
return Resources{}, errors.New("building not found")
|
|
}
|
|
|
|
}
|