• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DaniSomoza / galactic-commander / 12444891208

21 Dec 2024 11:46AM UTC coverage: 52.036% (-13.6%) from 65.587%
12444891208

Pull #11

github

web-flow
Merge 9b5ea0e56 into 4f9f087f0
Pull Request #11: Build units

206 of 789 branches covered (26.11%)

Branch coverage included in aggregate %.

366 of 898 new or added lines in 85 files covered. (40.76%)

10 existing lines in 7 files now uncovered.

1417 of 2330 relevant lines covered (60.82%)

3.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

14.29
/packages/game-api-microservice/src/services/buildUnitsService.ts
1
import playerRepository from 'game-engine/dist/repositories/playerRepository'
2✔
2
import taskRepository from 'game-engine/dist/repositories/taskRepository'
2✔
3
import universeRepository from 'game-engine/dist/repositories/universeRepository'
2✔
4
import planetRepository from 'game-engine/dist/repositories/planetRepository'
2✔
5
import createStartBuildUnitsTask from 'game-engine/dist/engine/tasks/utils/createStartBuildUnitsTask'
2✔
6
import NotFoundError from 'auth-microservice/dist/errors/NotFoundError'
2✔
7
import BadRequestError from 'auth-microservice/dist/errors/BadRequestError'
2✔
8
import ConflictError from 'auth-microservice/dist/errors/ConflictError'
2✔
9

10
import cleanPlayerFields from '../utils/cleanPlayerFields'
2✔
11
import { startResearchResponseType, updateResearchQueueResponseType } from '../types/Research'
12
import cleanTaskFields from '../utils/cleanTaskFields'
2✔
13
import { UnitTypes } from '../types/Unit'
14
import { PlanetCoordinatesType } from '../types/Planet'
15

16
type BuildUnitsData = {
17
  username: string
18
  unitName: string
19
  amount: number
20
  universeName: string
21
  executeTaskAt?: number
22
  planetCoordinates: PlanetCoordinatesType
23
}
24

25
async function startBuildUnits({
26
  username,
27
  unitName,
28
  amount,
29
  universeName,
30
  planetCoordinates,
31
  executeTaskAt
32
}: BuildUnitsData): Promise<startResearchResponseType> {
NEW
33
  const universe = await universeRepository.findUniverseByName(universeName)
×
34

NEW
35
  if (!universe) {
×
NEW
36
    throw new NotFoundError('invalid universe', { universeName })
×
37
  }
38

NEW
39
  const universeId = universe._id.toString()
×
40

NEW
41
  const player = await playerRepository.findPlayerByUsername(username, universeId)
×
42

NEW
43
  if (!player) {
×
NEW
44
    throw new NotFoundError('invalid player', { username, universeName })
×
45
  }
46

NEW
47
  const planet = await planetRepository.findPlanetByCoordinates(planetCoordinates)
×
48

NEW
49
  if (!planet) {
×
NEW
50
    throw new NotFoundError('invalid planet', {
×
51
      username,
52
      planetCoordinates
53
    })
54
  }
55

NEW
56
  const isValidPlanetOwner = planet.ownerId === player._id.toString()
×
57

NEW
58
  if (!isValidPlanetOwner) {
×
NEW
59
    throw new ConflictError('invalid planet owner', {
×
60
      username,
61
      planetCoordinates
62
    })
63
  }
64

NEW
65
  const raceUnit = player.race.units.find((unit) => unit.name === unitName)
×
NEW
66
  const planetUnit = planet.units.find((unit) => unit.name === unitName)
×
67

NEW
68
  const unit = raceUnit || planetUnit
×
69

NEW
70
  if (!unit) {
×
NEW
71
    throw new NotFoundError('invalid unit', { unitName })
×
72
  }
73

NEW
74
  if (executeTaskAt && executeTaskAt < new Date().getTime()) {
×
NEW
75
    throw new BadRequestError('invalid schedule', { executeTaskAt })
×
76
  }
77

78
  // TODO: checkActiveBuild ??? if executeTaskAt is not defined
79

NEW
80
  const startBuildUnitTask = createStartBuildUnitsTask(
×
81
    universeId,
82
    player._id.toString(),
83
    planet._id.toString(),
84
    unit._id.toString(),
85
    amount,
86
    executeTaskAt
87
  )
88

NEW
89
  const newTask = await taskRepository.createStartBuildUnitsTask(startBuildUnitTask)
×
90

NEW
91
  return { task: cleanTaskFields(newTask) }
×
92
}
93

94
type UpdateBuildUnitsQueueData = {
95
  username: string
96
  universeName: string
97
  unitType: UnitTypes
98
  buildUnitsQueue: {
99
    unitName: string
100
    amount: number
101
  }[]
102
  planetCoordinates: PlanetCoordinatesType
103
}
104

105
async function updateBuildUnitsQueue({
106
  username,
107
  universeName,
108
  unitType,
109
  buildUnitsQueue,
110
  planetCoordinates
111
}: UpdateBuildUnitsQueueData): Promise<updateResearchQueueResponseType> {
NEW
112
  const universe = await universeRepository.findUniverseByName(universeName)
×
113

NEW
114
  if (!universe) {
×
NEW
115
    throw new NotFoundError('invalid universe', { universeName })
×
116
  }
117

NEW
118
  const universeId = universe._id.toString()
×
119

NEW
120
  const player = await playerRepository.findPlayerByUsername(username, universeId)
×
121

NEW
122
  if (!player) {
×
NEW
123
    throw new NotFoundError('invalid player', { username, universeName })
×
124
  }
125

NEW
126
  const planet = await planetRepository.findPlanetByCoordinates(planetCoordinates)
×
127

NEW
128
  if (!planet) {
×
NEW
129
    throw new NotFoundError('invalid planet', {
×
130
      username,
131
      planetCoordinates
132
    })
133
  }
134

NEW
135
  const isValidPlanetOwner = planet.ownerId === player._id.toString()
×
136

NEW
137
  if (!isValidPlanetOwner) {
×
NEW
138
    throw new ConflictError('invalid planet owner', {
×
139
      username,
140
      planetCoordinates
141
    })
142
  }
143

NEW
144
  const isValidQueue = buildUnitsQueue.every(({ unitName }) => {
×
NEW
145
    const raceUnit = player.race.units.find((unit) => unit.name === unitName)
×
NEW
146
    const planetUnit = planet.units.find((unit) => unit.name === unitName)
×
147

NEW
148
    const unit = raceUnit || planetUnit
×
149

NEW
150
    return !!unit && unitType === unit.type
×
151
  })
152

NEW
153
  if (!isValidQueue) {
×
NEW
154
    throw new NotFoundError('invalid build units queue', { buildUnitsQueue })
×
155
  }
156

157
  // update planet build units queue
NEW
158
  const path: Record<UnitTypes, 'troops' | 'spaceships' | 'defenses'> = {
×
159
    TROOP: 'troops',
160
    SPACESHIP: 'spaceships',
161
    DEFENSE: 'defenses'
162
  }
163

NEW
164
  planet.unitBuild[path[unitType]].queue = buildUnitsQueue
×
165

NEW
166
  if (!planet.unitBuild[path[unitType]].activeBuild) {
×
167
    // if no build is active, just start building the first unit in the queue
NEW
168
    const nextBuildUnits = planet.unitBuild[path[unitType]].queue.shift()
×
NEW
169
    if (nextBuildUnits) {
×
NEW
170
      await startBuildUnits({
×
171
        username,
172
        unitName: nextBuildUnits.unitName,
173
        amount: nextBuildUnits.amount,
174
        planetCoordinates,
175
        universeName
176
      })
177
    }
178
  }
179

NEW
180
  await planet.save()
×
181

NEW
182
  return { player: cleanPlayerFields(player) }
×
183
}
184

185
const buildUnitsService = {
2✔
186
  startBuildUnits,
187
  updateBuildUnitsQueue
188
}
189

190
export default buildUnitsService
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc