gogame-old/services/gamesrv/gamesrv.go
services/gamesrv/gamesrv.goRaw
1package gamesrv
2
3import (
4 "errors"
5 "fmt"
6 "strconv"
7 "time"
8
9 "github.com/arnaucube/gogame/constants"
10 "github.com/arnaucube/gogame/database"
11 "github.com/arnaucube/gogame/models"
12 "github.com/arnaucube/gogame/utils"
13 "gopkg.in/mgo.v2/bson"
14)
15
16type Service struct {
17 db *database.Db
18}
19
20func New(db *database.Db) *Service {
21 return &Service{
22 db,
23 }
24}
25
26// CreatePlanet is used when a user conquers a planet
27func (srv Service) CreatePlanet(userId bson.ObjectId) (*models.SolarSystem, *models.Planet, error) {
28 size := int64(250) // TODO get rand inside a range
29 name := "planetname" // TODO get random name
30
31 newPlanet := models.Planet{
32 Size: size,
33 Name: name,
34 OwnerId: userId,
35 }
36 // in case that wants to start with resources plants
37 newPlanet.Buildings = make(map[string]int64)
38 newPlanet.Buildings["metalmine"] = 1
39 newPlanet.Buildings["crystalmine"] = 1
40 newPlanet.Buildings["deuteriummine"] = 1
41 newPlanet.Buildings["energymine"] = 1
42
43 err := srv.db.Planets.Insert(newPlanet)
44 if err != nil {
45 return nil, nil, err
46 }
47 var planet *models.Planet
48 err = srv.db.Planets.Find(bson.M{"ownerid": newPlanet.OwnerId}).One(&planet)
49 if err != nil {
50 return nil, nil, err
51 }
52
53 // now put the planet in a solar system
54 // get random solar system
55 systemPosition := utils.RandInRange(0, constants.GALAXYSIZE)
56 solarSystem, err := srv.PutPlanetInSolarSystem(systemPosition, planet)
57 // TODO if error is returned because there is no empty slots for planets in the solar system in systemPosition, get another systemPosition and try again
58
59 return solarSystem, planet, err
60}
61
62func (srv Service) PutPlanetInSolarSystem(position int64, planet *models.Planet) (*models.SolarSystem, error) {
63 var solarSystem models.SolarSystem
64 err := srv.db.SolarSystems.Find(bson.M{"position": position}).One(&solarSystem)
65 if err != nil {
66 // solar system non existing yet
67 // create a solarsystem with empty planets
68 var emptyPlanets []string
69 for i := 0; i < constants.SOLARSYSTEMSIZE; i++ {
70 emptyPlanets = append(emptyPlanets, "empty")
71 }
72 newSolarSystem := models.SolarSystem{
73 Position: position,
74 Planets: emptyPlanets[:15],
75 }
76 err = srv.db.SolarSystems.Insert(newSolarSystem)
77 if err != nil {
78 return nil, err
79 }
80 err := srv.db.SolarSystems.Find(bson.M{"position": position}).One(&solarSystem)
81
82 return &solarSystem, err
83 }
84 // get free slots in solarSystem
85 posInSolarSystem := utils.RandInRange(0, constants.SOLARSYSTEMSIZE)
86 if solarSystem.Planets[posInSolarSystem] != "" {
87 // not empty slot, take another one TODO
88 // if there are no empty slots, return error
89 fmt.Println("not empty slot")
90 }
91 // store planet in solar system
92 solarSystem.Planets[posInSolarSystem] = planet.Id.String()
93 err = srv.db.SolarSystems.Update(bson.M{"position": position}, solarSystem)
94
95 return &solarSystem, err
96}
97
98// CheckCurrentBuild checks if the planet has a ongoing building in process, and if has finished
99// in case that has finished, updates it in db
100func (srv Service) CheckCurrentBuild(planet *models.Planet) (bool, error) {
101 if planet.CurrentBuild.Title != "" {
102 // the planet is building something, check if has ended
103 if planet.CurrentBuild.Ends.Unix() < time.Now().Unix() {
104 // upgrade level of building in planet
105 planet.Buildings[planet.CurrentBuild.Building] += 1
106
107 // build end
108 planet.CurrentBuild.Title = ""
109 planet.CurrentBuild.Building = ""
110
111 // store in db
112 err := srv.db.Planets.Update(bson.M{"_id": planet.Id}, planet)
113 if err != nil {
114 return true, err
115 }
116 return false, nil
117 }
118 return true, nil
119 }
120 return false, nil
121
122}
123
124func (srv Service) GetBuildings(user *models.User, planetid bson.ObjectId) (*models.Planet, error) {
125 var planet models.Planet
126 err := srv.db.Planets.Find(bson.M{"_id": planetid, "ownerid": user.Id}).One(&planet)
127 if err != nil {
128 return nil, err
129 }
130 _, err = srv.CheckCurrentBuild(&planet)
131 return &planet, err
132}
133
134func (srv Service) UpgradeBuilding(user *models.User, planetid bson.ObjectId, building string) (*models.Planet, error) {
135 // get planet
136 var planet models.Planet
137 err := srv.db.Planets.Find(bson.M{"_id": planetid}).One(&planet)
138 if err != nil {
139 return nil, err
140 }
141 busy, err := srv.CheckCurrentBuild(&planet)
142 if err != nil {
143 return nil, err
144 }
145 if busy {
146 return nil, errors.New("busy")
147 }
148
149 // get current building level, and get the needed resources for next level
150 resourcesNeeded, err := user.GetBuildingCost(planet, building)
151 if err != nil {
152 return nil, err
153 }
154 // get time cost of the build
155 timei64 := models.ConstructionTime(resourcesNeeded, planet.Buildings[building]+1)
156 endsTime := time.Now().Add(time.Second * time.Duration(timei64))
157
158 // if user have enough resources to upgrade the building, upgrade the building
159 err = user.SpendResources(resourcesNeeded)
160 if err != nil {
161 return nil, err
162 }
163 // add current task to planet
164 planet.CurrentBuild.Building = building
165 planet.CurrentBuild.Title = building + " - Level " + strconv.Itoa(int(planet.Buildings[building]))
166 planet.CurrentBuild.Ends = endsTime
167
168 // store planet in db
169 err = srv.db.Planets.Update(bson.M{"_id": planet.Id}, planet)
170 return &planet, nil
171}