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