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

DaniSomoza / galactic-commander / 12457139241

22 Dec 2024 07:38PM UTC coverage: 52.086% (-13.5%) from 65.587%
12457139241

push

github

web-flow
Build units (#11)

* update models in game-engine

* added fleets

* add build unit service and troops page

* added build units dialog

* added build units queue

206 of 790 branches covered (26.08%)

Branch coverage included in aggregate %.

366 of 893 new or added lines in 84 files covered. (40.99%)

10 existing lines in 7 files now uncovered.

1417 of 2326 relevant lines covered (60.92%)

3.83 hits per line

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

15.73
/packages/game-engine/src/engine/tasks/processStartBuildUnitsTask.ts
1
import {
4✔
2
  ITask,
3
  PENDING_TASK_STATUS,
4
  StartBuildUnitsTaskType,
5
  FinishBuildUnitsTaskType,
6
  FINISH_BUILD_UNITS_TASK_TYPE
7
} from '../../types/ITask'
8
import getTaskModel, { ITaskTypeDocument } from '../../models/TaskModel'
4✔
9
import playerRepository from '../../repositories/playerRepository'
4✔
10
import GameEngineError from '../errors/GameEngineError'
4✔
11
import getSecond from '../../helpers/getSecond'
4✔
12
import checkUnitRequirements from '../units/checkUnitRequirements'
4✔
13
import isHeroAlreadyBuild from '../units/isHeroAlreadyBuild'
4✔
14
import isValidUnitAmount from '../units/isValidUnitAmount'
4✔
15
import computedBonus from '../bonus/computedBonus'
4✔
16
import { UnitTypes } from '../../types/IUnit'
17
import { IBonus } from '../../types/IBonus'
18
import { IPlanet } from '../../types/IPlanet'
19
import getPlayerUnit from '../units/getPlayerUnit'
4✔
20
import getFirstUnitInTheBuildQueue from '../units/getFirstUnitInTheBuildQueue'
4✔
21
import taskRepository from '../../repositories/taskRepository'
4✔
22
import createStartBuildUnitsTask from './utils/createStartBuildUnitsTask'
4✔
23

24
async function processStartBuildUnitsTask(
25
  task: ITaskTypeDocument<StartBuildUnitsTaskType>,
26
  second: number
27
) {
28
  // get all the required data from DB
NEW
29
  const player = await playerRepository.findPlayerById(task.data.playerId)
×
30

NEW
31
  if (!player) {
×
NEW
32
    throw new GameEngineError('invalid player')
×
33
  }
34

NEW
35
  const planet = player.planets.colonies.find(
×
NEW
36
    (playerColony) => playerColony._id.toString() === task.data.planetId
×
37
  )
38

NEW
39
  if (!planet) {
×
NEW
40
    throw new GameEngineError('invalid planet owner')
×
41
  }
42

NEW
43
  const unit = getPlayerUnit(player, task.data.build.unitId, planet)
×
44

NEW
45
  if (!unit) {
×
NEW
46
    throw new GameEngineError('invalid unit')
×
47
  }
48

NEW
49
  if (unit.type === 'TROOP' && !!planet.unitBuild.troops.activeBuild) {
×
NEW
50
    throw new GameEngineError('player already building troops in this planet')
×
51
  }
52

NEW
53
  if (unit.type === 'SPACESHIP' && !!planet.unitBuild.spaceships.activeBuild) {
×
NEW
54
    throw new GameEngineError('player already building spaceships in this planet')
×
55
  }
56

NEW
57
  if (unit.type === 'DEFENSE' && !!planet.unitBuild.defenses.activeBuild) {
×
NEW
58
    throw new GameEngineError('player already building defenses in this planet')
×
59
  }
60

NEW
61
  const buildUnitsType: Record<UnitTypes, keyof IPlanet['unitBuild']> = {
×
62
    TROOP: 'troops',
63
    SPACESHIP: 'spaceships',
64
    DEFENSE: 'defenses'
65
  }
66

NEW
67
  const { isUnitAvailable, requirements } = checkUnitRequirements(unit, player)
×
NEW
68
  const isValidAmount = isValidUnitAmount(unit, task.data.build.amount, player)
×
NEW
69
  const isHeroUnitAlreadyBuild = isHeroAlreadyBuild(unit, player.fleets)
×
70

NEW
71
  const resourceCost = unit.resourceCost * task.data.build.amount
×
NEW
72
  const unitEnergyCost = unit.energyCost || 0
×
NEW
73
  const energy = unitEnergyCost * task.data.build.amount
×
74

NEW
75
  const hasEnoughResources = planet.resources >= resourceCost
×
76

77
  const checkBuildUnitsQueue =
NEW
78
    !isUnitAvailable || !isValidAmount || isHeroUnitAlreadyBuild || !hasEnoughResources
×
79

NEW
80
  if (checkBuildUnitsQueue) {
×
NEW
81
    const nextBuildUnits = planet.unitBuild[buildUnitsType[unit.type]].queue.shift()
×
NEW
82
    const nextUnitInTheQueue = getFirstUnitInTheBuildQueue(player, planet, nextBuildUnits)
×
83

NEW
84
    if (nextUnitInTheQueue && nextBuildUnits) {
×
NEW
85
      const buildUnitsTask = createStartBuildUnitsTask(
×
86
        task.universeId,
87
        player._id.toString(),
88
        planet._id.toString(),
89
        nextUnitInTheQueue._id.toString(),
90
        nextBuildUnits.amount
91
      )
92

NEW
93
      await Promise.all([planet.save(), taskRepository.createStartBuildUnitsTask(buildUnitsTask)])
×
94
    }
95
  }
96

NEW
97
  if (!isUnitAvailable) {
×
NEW
98
    throw new GameEngineError('unit not available for this player', requirements)
×
99
  }
100

NEW
101
  if (!isValidAmount) {
×
NEW
102
    throw new GameEngineError('invalid unit amount')
×
103
  }
104

NEW
105
  if (isHeroUnitAlreadyBuild) {
×
NEW
106
    throw new GameEngineError('invalid unit, hero already build')
×
107
  }
108

NEW
109
  if (!hasEnoughResources) {
×
NEW
110
    throw new GameEngineError('no resources available', {
×
111
      resourceCost,
112
      planetResources: planet.resources
113
    })
114
  }
115

NEW
116
  const buildUnitsBono: Record<UnitTypes, keyof IBonus> = {
×
117
    TROOP: 'TROOPS_TRAINING_BONUS',
118
    SPACESHIP: 'FLEET_BUILDING_BONUS',
119
    DEFENSE: 'DEFENSES_BUILDING_BONUS'
120
  }
121

NEW
122
  const buildUnitsBonus = computedBonus(player.perks, buildUnitsBono[unit.type])
×
NEW
123
  const duration = task.data.build.amount * unit.buildBaseTime * (100 / buildUnitsBonus)
×
124

NEW
125
  const executeTaskAt = getSecond(second + duration)
×
126

127
  // TODO: implement createBaseTask helper function
NEW
128
  const finishBuildUnitsTask: ITask<FinishBuildUnitsTaskType> = {
×
129
    type: FINISH_BUILD_UNITS_TASK_TYPE,
130
    universeId: player.universeId,
131
    data: {
132
      playerId: player._id.toString(),
133
      planetId: planet._id.toString(),
134
      build: {
135
        unitId: task.data.build.unitId,
136
        amount: task.data.build.amount,
137
        unitType: unit.type,
138
        duration,
139
        resourceCost,
140
        energy
141
      }
142
    },
143
    status: PENDING_TASK_STATUS,
144
    isCancellable: true,
145
    executeTaskAt,
146
    processedAt: null,
147
    processingDuration: null,
148
    history: [
149
      {
150
        taskStatus: PENDING_TASK_STATUS,
151
        updatedAt: new Date().getTime()
152
      }
153
    ],
154
    errorDetails: null
155
  }
NEW
156
  const taskModel = getTaskModel<FinishBuildUnitsTaskType>()
×
NEW
157
  const newTask = new taskModel(finishBuildUnitsTask)
×
158

NEW
159
  planet.unitBuild[buildUnitsType[unit.type]].activeBuild = {
×
160
    unitId: unit._id.toString(),
161
    unitName: unit.name,
162
    unitType: unit.type,
163
    amount: task.data.build.amount,
164
    taskId: newTask._id.toString(),
165
    executeTaskAt,
166
    energy,
167
    resourceCost
168
  }
169

NEW
170
  planet.resources -= resourceCost
×
171

NEW
172
  return Promise.all([newTask.save(), planet.save(), player.save()])
×
173
}
174

175
export default processStartBuildUnitsTask
4✔
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