GameSetupManager::setupGameFromDatabase()   B
last analyzed

Complexity

Conditions 9
Paths 64

Size

Total Lines 113
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 51
CRAP Score 9.0043

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 52
c 1
b 0
f 0
nc 64
nop 0
dl 0
loc 113
ccs 51
cts 53
cp 0.9623
crap 9.0043
rs 7.4917

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace App\Adventure\Utils;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use Doctrine\Persistence\ObjectManager;
7
use App\Entity\Game\Location;
8
use App\Entity\Game\Item;
9
use App\Entity\Game\Action;
10
use App\Entity\Game\Response;
11
use App\Entity\Game\Connection;
12
use App\Adventure\Location as GameLocation;
13
use App\Adventure\Item as GameItem;
14
use App\Adventure\Game;
15
use App\Adventure\ActionResponses\LocationResponseInterface;
16
use App\Adventure\InputActions\ExamineAction;
17
use App\Adventure\InputActions\TakeAction;
18
use App\Adventure\InputActions\UseAction;
19
use Exception;
20
21
/**
22
 * Handles setting up the game from the database.
23
 */
24
class GameSetupManager
25
{
26
    /**
27
     * @var EntityManagerInterface|ObjectManager
28
     */
29
    private $entityManager;
30
31
    /**
32
     * GameSetupManager constructor.
33
     *
34
     * @param EntityManagerInterface|ObjectManager $entityManager The Doctrine entity manager.
35
     */
36 1
    public function __construct(EntityManagerInterface|ObjectManager $entityManager)
37
    {
38 1
        $this->entityManager = $entityManager;
39
    }
40
41
    /**
42
     * Retrieves the fully qualified class name for the action based on the provided type.
43
     *
44
     * @param string $type The type of the action.
45
     *
46
     * @return string|null The fully qualified class name if it exists, or null if not found.
47
     */
48 1
    private function getActionClass(string $type): ?string
49
    {
50 1
        $namespace = 'App\Adventure\InputActions';
51
52 1
        $actionClasses = [
53 1
            'examine' => 'ExamineAction',
54 1
            'take' => 'TakeAction',
55 1
            'use' => 'UseAction',
56 1
        ];
57
58 1
        $type = trim(strtolower($type));
59
60 1
        $actionClass = $namespace . '\\' . $actionClasses[$type];
61
62 1
        if (class_exists($actionClass)) {
63 1
            return $actionClass;
64
        }
65
66
        return null;
67
    }
68
69
    /**
70
     * Retrieves the fully qualified class name for the response based on the provided type.
71
     *
72
     * @param string $type The type of the response.
73
     *
74
     * @return string|null The fully qualified class name if it exists, or null if not found.
75
     */
76 1
    private function getResponseClass(string $type): ?string
77
    {
78 1
        $namespace = 'App\Adventure\ActionResponses';
79
80 1
        $responseClasses = [
81 1
            'swap' => 'SwapLocationResponse',
82 1
            'move' => 'MoveLocationResponse',
83 1
        ];
84
85 1
        $type = trim(strtolower($type));
86
87 1
        $responseClass = $namespace . '\\' . $responseClasses[$type];
88
89 1
        if (class_exists($responseClass)) {
90 1
            return $responseClass;
91
        }
92
93
        return null;
94
    }
95
96
    /**
97
     * Sets up the game from the database.
98
     *
99
     * @return Game The configured game instance.
100
     * @throws Exception If any error occurs during the setup process.
101
     *
102
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
103
     */
104 1
    public function setupGameFromDatabase(): Game
105
    {
106
        // Fetch data from database
107 1
        $locationData = $this->entityManager->getRepository(Location::class)->findAll();
108 1
        $itemData = $this->entityManager->getRepository(Item::class)->findAll();
109 1
        $actionData = $this->entityManager->getRepository(Action::class)->findAll();
110 1
        $responseData = $this->entityManager->getRepository(Response::class)->findAll();
111 1
        $connectionData = $this->entityManager->getRepository(Connection::class)->findAll();
112
113
        // Lookup arrays for easy access
114 1
        $locationsLookup = [];
115 1
        $itemsLookup = [];
116 1
        $actionsLookup = [];
117
118
        // Create locations and populate lookup array
119 1
        foreach ($locationData as $data) {
120
            /** @var string */
121 1
            $name = $data->getName();
122
            /** @var string */
123 1
            $description = $data->getDescription();
124
            /** @var string */
125 1
            $locationDetails = $data->getDetails();
126
127 1
            $location = new GameLocation($name, $description, $locationDetails);
128 1
            $locationsLookup[$data->getId()] = $location;
129
        }
130
131
        // Create items and place them in locations, and populate lookup array
132 1
        foreach ($itemData as $data) {
133
            /** @var string */
134 1
            $name = $data->getName();
135
            /** @var string */
136 1
            $description = $data->getDescription();
137
138 1
            $item = new GameItem($name, $description);
139 1
            $itemsLookup[$data->getId()] = $item;
140
141
            // Place item in location
142 1
            $inLocation = $locationsLookup[$data->getLocationId()];
143 1
            $inLocation->addItem($item);
144
        }
145
146
        // Create actions and add them to the corresponding items, and populate lookup array
147 1
        foreach ($actionData as $data) {
148
            /** @var string */
149 1
            $actionType = $data->getType();
150
151
            // Retrieve the corrsponging action class
152 1
            $actionClass = $this->getActionClass($actionType);
153
154 1
            if ($actionClass === null) {
155
                throw new Exception('Action class not found for type: ' . $actionType);
156
            }
157
158
            /**
159
             * @var ExamineAction|TakeAction|UseAction
160
             */
161 1
            $action = new $actionClass($data->getDescription());
162
163
            // Set required location, if applicable
164 1
            $locationId = $data->getRequiredLocationId();
165 1
            if ($locationId) {
166 1
                $requiredLocation = $locationsLookup[$locationId];
167 1
                $action->setRequiredLocation($requiredLocation);
168
            }
169
170
            // Add action to item
171 1
            $item = $itemsLookup[$data->getItemId()];
172 1
            $item->addAction($action);
173
174 1
            $actionsLookup[$data->getId()] = $action;
175
        }
176
177
        // Create responses and add them to the corresponding actions
178 1
        foreach ($responseData as $data) {
179
            /** @var string */
180 1
            $responseType = $data->getType();
181
182
            // Retrieve the corrsponging response class
183 1
            $responseClass = $this->getResponseClass($responseType);
184
185 1
            if ($responseClass === null) {
186
                throw new Exception('Response class not found for type: ' . $data->getType());
187
            }
188
189
            // Add response location to either swap in or move to when action is triggered
190 1
            $location = $locationsLookup[$data->getLocationId()];
191
192
            /** @var LocationResponseInterface */
193 1
            $response = new $responseClass($location);
194
195
            // Add response to action
196 1
            $action = $actionsLookup[$data->getActionId()];
197 1
            $action->setLocationResponse($response);
198
        }
199
200
        // Create connections between locations
201 1
        foreach ($connectionData as $data) {
202 1
            $fromLocation = $locationsLookup[$data->getFromLocationId()];
203 1
            $toLocation = $locationsLookup[$data->getToLocationId()];
204
205
            /** @var string */
206 1
            $direction = $data->getDirection();
207 1
            $direction = trim(strtolower($direction));
208
209 1
            $fromLocation->connectTo($toLocation, $direction);
210
        }
211
212
        // Create game instance and set starting location
213 1
        $game = new Game();
214 1
        $game->setCurrentLocation($locationsLookup[1]);
215
216 1
        return $game;
217
    }
218
}
219