Skip to content

Commit

Permalink
Filter out completed requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
rautamik committed Nov 16, 2024
1 parent ba2f465 commit 77bda98
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 76 deletions.
160 changes: 90 additions & 70 deletions app/Services/ObjectService.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use OGame\GameObjects\Models\BuildingObject;
use OGame\GameObjects\Models\DefenseObject;
use OGame\GameObjects\Models\Enums\GameObjectType;
use OGame\GameObjects\Models\Fields\GameObjectRequirement;
use OGame\GameObjects\Models\ResearchObject;
use OGame\GameObjects\Models\ShipObject;
use OGame\GameObjects\Models\StationObject;
Expand Down Expand Up @@ -333,34 +334,12 @@ public static function getBuildingObjectsWithStorage(): array
*/
public static function objectRequirementsMet(string $machine_name, PlanetService $planet, PlayerService $player): bool
{
try {
$object = self::getObjectByMachineName($machine_name);

foreach ($object->requirements as $requirement) {
// Load required object and check if requirements are met.
$object_required = self::getObjectByMachineName($requirement->object_machine_name);

if ($object_required->type === GameObjectType::Research) {
// Check if requirements are met with existing technology.
if ($player->getResearchLevel($object_required->machine_name) < $requirement->level) {
return false;
}
} else {
// Check if requirements are met with existing buildings.
if ($planet->getObjectLevel($object_required->machine_name) < $requirement->level) {
return false;
}
}
}
} catch (Exception $e) {
return false;
}

return true;
$object = self::getObjectByMachineName($machine_name);
return count(self::filterCompletedRequirements($object->requirements, $planet, $player)) === 0;
}

/**
* Check if object requirements are met (for building it).
* Check if object requirements are met (for building it) with previous levels completed.
*
* @param string $machine_name
* @param PlanetService $planet
Expand All @@ -373,21 +352,21 @@ public static function objectRequirementsWithLevelsMet(string $machine_name, int
try {
$object = self::getObjectByMachineName($machine_name);

// Check that the object's previous levels exist.
// Check that the object's previous level exists.
if ($target_level) {
if (!self::hasRequiredLevels($target_level, $object, $planet, $player)) {
if (!self::hasPreviousLevels($target_level, $object, $planet, $player)) {
return false;
}
}
} catch (Exception $e) {
return false;
}

return self::objectRequirementsMet($machine_name, $planet, $player);
return count(self::filterCompletedRequirements($object->requirements, $planet, $player)) === 0;
}

/**
* Check if object requirements are met with existing and queued items (for building it).
* Check if object requirements are met (for building it) with existing and queued items.
*
* @param string $machine_name
* @param PlanetService $planet
Expand All @@ -398,49 +377,18 @@ public static function objectRequirementsWithLevelsMet(string $machine_name, int
public static function objectRequirementsMetWithQueue(string $machine_name, int $target_level, PlanetService $planet, PlayerService $player): bool
{
// Check the object's requirements against the existing objects
if (self::objectRequirementsWithLevelsMet($machine_name, $target_level, $planet, $player)) {
return true;
}

// Check the object’s requirements against the queued objects.
try {
$object = self::getObjectByMachineName($machine_name);

if (!self::hasRequiredLevelsInQueue($target_level, $object, $planet, $player)) {
return false;
}

foreach ($object->requirements as $requirement) {
// Load required object and check if requirements are met.
$object_required = self::getObjectByMachineName($requirement->object_machine_name);

// Skip the queue check for the research lab, as it must be present for research objects.
if ($object_required->machine_name === 'research_lab') {
if ($planet->getObjectLevel('research_lab') === $requirement->level) {
continue;
} else {
return false;
}
}
$object = self::getObjectByMachineName($machine_name);
$incompleteRequirements = self::filterCompletedRequirements($object->requirements, $planet, $player);

if ($object_required->type === GameObjectType::Research) {
// Check if the requirements are met by the items in the research queue.
if (!$player->isResearchingTech($requirement->object_machine_name, $requirement->level)) {
return false;
}
} else {
// Check if the requirements are met by the items in the building queue.
// The building queue is checked only for building queue objects, not for unit queue objects.
if (!$planet->isBuildingObject($requirement->object_machine_name, $requirement->level)) {
return false;
}
}
}
} catch (Exception $e) {
if (!self::hasPreviousLevelsInQueue($target_level, $object, $planet, $player)) {
return false;
}

return true;
if (count($incompleteRequirements) === 0) {
return true;
}

return count(self::filterQueuedRequirements($incompleteRequirements, $planet, $player)) === 0;
}

/**
Expand Down Expand Up @@ -575,6 +523,78 @@ public static function getObjectRawPrice(string $machine_name, int $level = 0):
return new Resources($metal, $crystal, $deuterium, $energy);
}

/**
* Filter out completed requirements.
*
* @param array<GameObjectRequirement> $requirements
* @param PlanetService $planet
* @param PlayerService $player
* @return array<GameObjectRequirement>
*/
private static function filterCompletedRequirements(array $requirements, PlanetService $planet, PlayerService $player): array
{
return array_filter($requirements, function ($requirement) use ($planet, $player) {
try {
$object = self::getObjectByMachineName($requirement->object_machine_name);

if ($object->type === GameObjectType::Research) {
// Check if requirements are met with existing technology.
if ($player->getResearchLevel($requirement->object_machine_name) < $requirement->level) {
return true;
}
} else {
// Check if requirements are met with existing buildings.
if ($planet->getObjectLevel($requirement->object_machine_name) < $requirement->level) {
return true;
}
}

return false;
} catch (Exception $e) {
return true;
}
});
}

/**
* Filter out queued requirements.
*
* @param array<GameObjectRequirement> $requirements
* @param PlanetService $planet
* @param PlayerService $player
* @return array<GameObjectRequirement>
*/
private static function filterQueuedRequirements(array $requirements, PlanetService $planet, PlayerService $player): array
{
return array_filter($requirements, function ($requirement) use ($planet, $player) {
try {
$object = self::getObjectByMachineName($requirement->object_machine_name);

// Skip the queue check for the research lab, as it must be present for research objects.
if ($requirement->object_machine_name === 'research_lab') {
return ($planet->getObjectLevel('research_lab') !== $requirement->level);
}

if ($object->type === GameObjectType::Research) {
// Check if the requirements are met by the items in the research queue.
if (!$player->isResearchingTech($requirement->object_machine_name, $requirement->level)) {
return true;
}
} else {
// Check if the requirements are met by the items in the building queue.
// The building queue is checked only for building queue objects, not for unit queue objects.
if (!$planet->isBuildingObject($requirement->object_machine_name, $requirement->level)) {
return true;
}
}

return false;
} catch (Exception $e) {
return true;
}
});
}

/**
* Check if object previous level requirements are met (for building it).
*
Expand All @@ -584,7 +604,7 @@ public static function getObjectRawPrice(string $machine_name, int $level = 0):
* @param PlayerService $player
* @return bool
*/
private static function hasRequiredLevels(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool
private static function hasPreviousLevels(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool
{
$current_level = 0;

Expand All @@ -611,7 +631,7 @@ private static function hasRequiredLevels(int $target_level, GameObject $object,
* @param PlayerService $player
* @return bool
*/
private static function hasRequiredLevelsInQueue(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool
private static function hasPreviousLevelsInQueue(int $target_level, GameObject $object, PlanetService $planet, PlayerService $player): bool
{
// Check prior levels from queues
$current_level = 0;
Expand Down
15 changes: 9 additions & 6 deletions app/Services/ResearchQueueService.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public function add(PlayerService $player, PlanetService $planet, int $research_

// Check to see how many other items of this technology there are already
// in the queue, because if so then the level needs to be higher than that.
$amount = $this->activeBuildingQueueItemCount($player, $research_object_id);
$amount = $this->activeResearchQueueItemCount($player, $research_object_id);
$next_level = $current_level + $amount + 1;

// Check if user satisifes requirements to research this object.
Expand All @@ -147,6 +147,10 @@ public function add(PlayerService $player, PlanetService $planet, int $research_
/**
* Retrieve current research queue for a planet.
*
* @TODO this function is not retrieving the queue for a planet
* like the comment says, instead the queue is retrieved for a player.
* Bug or incorrect comment?
*
* @param PlanetService $planet
* @return ResearchQueueListViewModel
* @throws Exception
Expand Down Expand Up @@ -193,22 +197,21 @@ public function retrieveQueue(PlanetService $planet): ResearchQueueListViewModel
}

/**
* Get the amount of already existing queue items for a particular
* building.
* Get the amount of player active research queue items.
*
* @param PlayerService $player
* @param int $building_id
* @param int $tech_id
* @return int
*/
public function activeBuildingQueueItemCount(PlayerService $player, int $building_id): int
public function activeResearchQueueItemCount(PlayerService $player, int $tech_id = 0): int
{
// Fetch queue items from model
return $this->model
->join('planets', 'research_queues.planet_id', '=', 'planets.id')
->join('users', 'planets.user_id', '=', 'users.id')
->where([
['users.id', $player->getId()],
['research_queues.object_id', $building_id],
['research_queues.object_id', $tech_id],
['research_queues.processed', 0],
['research_queues.canceled', 0],
])
Expand Down

0 comments on commit 77bda98

Please sign in to comment.