GameSetupManager::getActionClass()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2.0023

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 10
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 19
ccs 11
cts 12
cp 0.9167
crap 2.0023
rs 9.9332
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