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

DaniSomoza / galactic-commander / 11940541664

20 Nov 2024 07:39PM UTC coverage: 65.587% (-31.2%) from 96.824%
11940541664

push

github

web-flow
Frontend initial implementation and player perks feature (#10)

* added vite react-ts template

* Add register and login pages

* Add initial frontend implementation

* Add first iteration of research queue

* first version of the research page

* added assets

* Added pirate research assets

* Added translation support

* updated planet images

* added first version of the bonus

181 of 418 branches covered (43.3%)

Branch coverage included in aggregate %.

532 of 983 new or added lines in 110 files covered. (54.12%)

8 existing lines in 4 files now uncovered.

1176 of 1651 relevant lines covered (71.23%)

4.75 hits per line

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

95.38
/packages/game-engine/src/engine/processTasks.ts
1
import { MongoServerError } from 'mongodb'
4✔
2

3
import groupTasksBySeconds from '../helpers/groupTasksBySeconds'
4✔
4
import {
4✔
5
  ERROR_TASK_STATUS,
6
  FINISH_RESEARCH_TASK_TYPE,
7
  FinishResearchTaskData,
8
  ITaskDocument,
9
  ITaskTypeDocument,
10
  NEW_PLAYER_TASK_TYPE,
11
  NewPlayerTaskData,
12
  PROCESSED_TASK_STATUS,
13
  START_RESEARCH_TASK_TYPE,
14
  StartResearchTaskData,
15
  TaskType
16
} from '../models/TaskModel'
17
import taskRepository from '../repositories/taskRepository'
4✔
18
import playerRepository from '../repositories/playerRepository'
4✔
19
import GameEngineError from './errors/GameEngineError'
4✔
20
import { IUniverseDocument } from '../models/UniverseModel'
21
import { IPlanetDocument } from '../models/PlanetModel'
22
import { IPlayerDocument } from '../models/PlayerModel'
23
import calculateResourceProduction from './resources/calculateResourceProduction'
4✔
24
import { TASK_HANDLER, TaskHandler } from './tasks/taskHandlers'
4✔
25
import computedBonus from './bonus/computedBonus'
4✔
26

27
async function processTasks(tasks: ITaskDocument[], universe: IUniverseDocument) {
28
  const tasksGroupedBySeconds = groupTasksBySeconds(tasks, universe)
23✔
29

30
  for (const { tasks, second } of tasksGroupedBySeconds) {
23✔
31
    // 0.- Calculate player resources
32
    await processResourceProduction(tasks, second)
23✔
33

34
    // 1.- New player Tasks
35
    const newPlayerTasks = tasks.filter((task) => task.type === NEW_PLAYER_TASK_TYPE)
23✔
36

37
    const newPlayerTaskHandler = TASK_HANDLER[NEW_PLAYER_TASK_TYPE].handler
23✔
38

39
    await processTasksSequentially(newPlayerTasks, newPlayerTaskHandler, second)
23✔
40

41
    // 2.- Finish Research Tasks
42
    const finishResearchTaskHandler = TASK_HANDLER[FINISH_RESEARCH_TASK_TYPE].handler
23✔
43

44
    const finishResearchTasks = tasks.filter((task) => task.type === FINISH_RESEARCH_TASK_TYPE)
23✔
45
    await processTasksInParallel(finishResearchTasks, finishResearchTaskHandler, second)
23✔
46

47
    // 3.- Start Research Tasks
48
    const startResearchTaskHandler = TASK_HANDLER[START_RESEARCH_TASK_TYPE].handler
23✔
49

50
    // we can have new startResearchTasks generated by the finishResearchTaskHandler
51
    const startResearchTasks = await taskRepository.getPendingTasksByType(
23✔
52
      universe._id,
53
      second,
54
      START_RESEARCH_TASK_TYPE
55
    )
56
    await processTasksSequentially(startResearchTasks, startResearchTaskHandler, second)
23✔
57

58
    // update universe
59
    universe.lastProcessedTime = second
23✔
60
    await universe.save()
23✔
61
  }
62
}
63

64
export default processTasks
4✔
65

66
// TODO: add tests here
67
async function processTasksSequentially<Type extends TaskType>(
68
  tasks: ITaskDocument[],
69
  handler: TaskHandler<Type>,
70
  second: number
71
) {
72
  for (const task of tasks) {
46✔
73
    await setTaskAsProcessed(task, handler, second)
12✔
74
  }
75
}
76

77
async function processTasksInParallel<Type extends TaskType>(
78
  tasks: ITaskDocument[],
79
  handler: TaskHandler<Type>,
80
  second: number
81
) {
82
  return Promise.all(tasks.map((task) => setTaskAsProcessed(task, handler, second)))
23✔
83
}
84

85
async function setTaskAsProcessed<Type extends TaskType>(
86
  task: ITaskDocument,
87
  handler: TaskHandler<Type>,
88
  second: number
89
) {
90
  const startTime = new Date().getTime()
23✔
91
  try {
23✔
92
    await handler(task as ITaskTypeDocument<Type>, second)
23✔
93
    task.status = PROCESSED_TASK_STATUS
13✔
94
    task.history.push({ taskStatus: PROCESSED_TASK_STATUS, updatedAt: new Date().getTime() })
13✔
95
  } catch (error) {
96
    if (error instanceof MongoServerError) {
10!
97
      task.errorDetails = error.message
×
98
    }
99
    if (error instanceof GameEngineError) {
10✔
100
      task.errorDetails = error.message
10✔
101
    }
102

103
    task.status = ERROR_TASK_STATUS
10✔
104
    task.history.push({ taskStatus: ERROR_TASK_STATUS, updatedAt: new Date().getTime() })
10✔
105
  }
106

107
  task.isCancellable = false
23✔
108
  task.processedAt = second
23✔
109
  const endTime = new Date().getTime()
23✔
110
  task.processingDuration = endTime - startTime
23✔
111
  return task.save()
23✔
112
}
113

114
async function processResourceProduction(
115
  tasks: ITaskTypeDocument<TaskType>[],
116
  second: number
117
): Promise<IPlanetDocument[]> {
118
  const planets: {
119
    planet: IPlanetDocument
120
    owner: IPlayerDocument
121
  }[] = []
23✔
122

123
  // TODO: implement targetPlanet feature
124
  for (const task of tasks) {
23✔
125
    // calculate all player planet production
126
    if (isPlayerTaskData(task.data)) {
23✔
127
      const player = await playerRepository.findPlayerById(task.data.player)
17✔
128

129
      if (player) {
17✔
130
        const playerPlanets = player.planets.colonies
15✔
131

132
        playerPlanets.forEach((playerPlanet) => {
15✔
133
          const isAlreadyIncluded = planets.some(({ planet }) =>
15✔
NEW
134
            planet._id.equals(playerPlanet._id)
×
135
          )
136

137
          if (!isAlreadyIncluded) {
15✔
138
            planets.push({
15✔
139
              planet: playerPlanet,
140
              owner: player
141
            })
142
          }
143
        })
144
      }
145
    }
146
  }
147

148
  return Promise.all(
23✔
149
    planets.map(({ planet, owner }) => {
150
      const ownerResourceProductionBonus = computedBonus(owner.perks, 'RESOURCE_PRODUCTION_BONUS')
15✔
151

152
      planet.resources = calculateResourceProduction(
15✔
153
        second,
154
        planet.resources,
155
        planet.lastResourceProductionTime,
156
        planet.resourceQuality,
157
        ownerResourceProductionBonus
158
      )
159
      planet.lastResourceProductionTime = second
15✔
160

161
      return planet.save()
15✔
162
    })
163
  )
164
}
165

166
function isPlayerTaskData(
167
  taskData: NewPlayerTaskData | StartResearchTaskData | FinishResearchTaskData
168
): taskData is StartResearchTaskData | FinishResearchTaskData {
169
  return 'player' in taskData
23✔
170
}
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