From 68670bb1753597adb117562305b61083e0cd88f9 Mon Sep 17 00:00:00 2001 From: g5bot Date: Fri, 20 Jun 2025 18:27:14 +0200 Subject: [PATCH 1/3] complete rump role enum --- src/Component/Spacecraft/SpacecraftRumpRoleEnum.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Component/Spacecraft/SpacecraftRumpRoleEnum.php b/src/Component/Spacecraft/SpacecraftRumpRoleEnum.php index 8dbe91e15..cda66f56e 100644 --- a/src/Component/Spacecraft/SpacecraftRumpRoleEnum.php +++ b/src/Component/Spacecraft/SpacecraftRumpRoleEnum.php @@ -23,4 +23,6 @@ enum SpacecraftRumpRoleEnum: int case SHIP_ROLE_SENSOR = 14; case SHIP_ROLE_OUTPOST = 15; case SHIP_ROLE_BASE = 16; + case SHIP_ROLE_ADVENT_DOOR = 17; + case SHIP_ROLE_THOLIAN_WEB = 18; } From 8b89155110896abaf2743724da76c5b6196a63ef Mon Sep 17 00:00:00 2001 From: g5bot Date: Fri, 20 Jun 2025 21:09:24 +0200 Subject: [PATCH 2/3] refactoring --- .../{Version20250619092058.php => Version20250620190641.php} | 2 +- src/Orm/Entity/Module.php | 2 +- src/Orm/Entity/ShipRumpCategory.php | 4 +++- src/Orm/Entity/ShipRumpCategoryRoleCrew.php | 2 +- src/Orm/Entity/ShipRumpRole.php | 4 +++- src/Orm/Entity/SpacecraftRump.php | 4 ++-- 6 files changed, 11 insertions(+), 7 deletions(-) rename src/Migrations/Sqlite/{Version20250619092058.php => Version20250620190641.php} (99%) diff --git a/src/Migrations/Sqlite/Version20250619092058.php b/src/Migrations/Sqlite/Version20250620190641.php similarity index 99% rename from src/Migrations/Sqlite/Version20250619092058.php rename to src/Migrations/Sqlite/Version20250620190641.php index af1d51c50..0e2c1ffaf 100644 --- a/src/Migrations/Sqlite/Version20250619092058.php +++ b/src/Migrations/Sqlite/Version20250620190641.php @@ -10,7 +10,7 @@ /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20250619092058 extends AbstractMigration +final class Version20250620190641 extends AbstractMigration { public function getDescription(): string { diff --git a/src/Orm/Entity/Module.php b/src/Orm/Entity/Module.php index 59507917c..cced47598 100644 --- a/src/Orm/Entity/Module.php +++ b/src/Orm/Entity/Module.php @@ -64,7 +64,7 @@ class Module implements ModuleInterface #[Column(type: 'boolean')] private bool $viewable = false; - #[Column(type: 'enum', enumType: SpacecraftRumpRoleEnum::class, nullable: true)] + #[Column(type: 'integer', enumType: SpacecraftRumpRoleEnum::class, nullable: true)] private ?SpacecraftRumpRoleEnum $rumps_role_id = null; #[Column(type: 'smallint')] diff --git a/src/Orm/Entity/ShipRumpCategory.php b/src/Orm/Entity/ShipRumpCategory.php index 3e0c2ce9f..c13dfae2e 100644 --- a/src/Orm/Entity/ShipRumpCategory.php +++ b/src/Orm/Entity/ShipRumpCategory.php @@ -6,6 +6,7 @@ use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\GeneratedValue; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\JoinColumn; use Doctrine\ORM\Mapping\ManyToOne; @@ -20,7 +21,8 @@ class ShipRumpCategory implements ShipRumpCategoryInterface { #[Id] - #[Column(type: 'enum', enumType: SpacecraftRumpCategoryEnum::class)] + #[GeneratedValue(strategy: 'IDENTITY')] + #[Column(type: 'integer', enumType: SpacecraftRumpCategoryEnum::class)] private SpacecraftRumpCategoryEnum $id; #[Column(type: 'string')] diff --git a/src/Orm/Entity/ShipRumpCategoryRoleCrew.php b/src/Orm/Entity/ShipRumpCategoryRoleCrew.php index 556c4ec4f..9eb1a55b5 100644 --- a/src/Orm/Entity/ShipRumpCategoryRoleCrew.php +++ b/src/Orm/Entity/ShipRumpCategoryRoleCrew.php @@ -29,7 +29,7 @@ class ShipRumpCategoryRoleCrew implements ShipRumpCategoryRoleCrewInterface #[Column(type: 'integer')] private int $rump_category_id = 0; - #[Column(type: 'enum', enumType: SpacecraftRumpRoleEnum::class)] + #[Column(type: 'integer', enumType: SpacecraftRumpRoleEnum::class)] private SpacecraftRumpRoleEnum $rump_role_id; #[Column(type: 'smallint')] diff --git a/src/Orm/Entity/ShipRumpRole.php b/src/Orm/Entity/ShipRumpRole.php index 7ef167b85..5250de1bb 100644 --- a/src/Orm/Entity/ShipRumpRole.php +++ b/src/Orm/Entity/ShipRumpRole.php @@ -6,6 +6,7 @@ use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\GeneratedValue; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\Table; use Override; @@ -17,7 +18,8 @@ class ShipRumpRole implements ShipRumpRoleInterface { #[Id] - #[Column(type: 'enum', enumType: SpacecraftRumpRoleEnum::class)] + #[GeneratedValue(strategy: 'IDENTITY')] + #[Column(type: 'integer', enumType: SpacecraftRumpRoleEnum::class)] private SpacecraftRumpRoleEnum $id; #[Column(type: 'string')] diff --git a/src/Orm/Entity/SpacecraftRump.php b/src/Orm/Entity/SpacecraftRump.php index a90e2867d..d651596ff 100644 --- a/src/Orm/Entity/SpacecraftRump.php +++ b/src/Orm/Entity/SpacecraftRump.php @@ -31,10 +31,10 @@ class SpacecraftRump implements SpacecraftRumpInterface #[GeneratedValue(strategy: 'IDENTITY')] private int $id; - #[column(type: 'enum', enumType: SpacecraftRumpCategoryEnum::class, nullable: false)] + #[column(type: 'integer', enumType: SpacecraftRumpCategoryEnum::class, nullable: false)] private SpacecraftRumpCategoryEnum $category_id; - #[column(type: 'enum', enumType: SpacecraftRumpRoleEnum::class, nullable: true)] + #[column(type: 'integer', enumType: SpacecraftRumpRoleEnum::class, nullable: true)] private ?SpacecraftRumpRoleEnum $role_id = null; #[column(type: 'smallint')] From a0cfe4f901e69affff81aea5e5a2699e6bae87a3 Mon Sep 17 00:00:00 2001 From: Janko Date: Sun, 9 Feb 2025 12:47:10 +0100 Subject: [PATCH 3/3] introduce crew skills and enhancement --- phpstan-baseline.neon | 6 + src/Component/Crew/CrewEnum.php | 63 ----- src/Component/Crew/CrewGenderEnum.php | 19 ++ src/Component/Crew/CrewPositionEnum.php | 56 +++++ .../Crew/Skill/CreateEnhancementLog.php | 50 ++++ .../Crew/Skill/CrewEnhancemenProxy.php | 25 ++ src/Component/Crew/Skill/CrewEnhancement.php | 49 ++++ .../Crew/Skill/CrewEnhancementInterface.php | 17 ++ .../Crew/Skill/CrewSkillLevelEnum.php | 83 +++++++ src/Component/Crew/Skill/RaiseExpertise.php | 61 +++++ .../Crew/Skill/SkillEnhancementCache.php | 41 ++++ .../Skill/SkillEnhancementCacheInterface.php | 13 + .../Crew/Skill/SkillEnhancementEnum.php | 13 + src/Component/Crew/services.php | 11 + .../Spacecraft/Repair/RepairUtil.php | 4 +- .../System/Type/TroopQuartersShipSystem.php | 2 +- .../Provider/ManagerProviderColony.php | 2 +- .../Provider/ManagerProviderStation.php | 2 +- ...20190641.php => Version20250620191610.php} | 36 ++- ...Version20250113065603_Crew_Assignments.php | 26 ++ .../Version20250113075911_Skill_Level.php | 29 +++ ...ersion20250113194515_Skill_Enhancement.php | 27 +++ .../Version20250114095354_Enhancement_Log.php | 32 +++ .../pgsql/Version20250114140100.php | 30 +++ .../pgsql/Version20250114145656.php | 26 ++ .../pgsql/Version20250203092918.php | 1 - .../StartAirfieldShip/StartAirfieldShip.php | 2 +- src/Module/Crew/Lib/CrewCreator.php | 59 ++--- src/Module/Crew/Lib/CrewCreatorInterface.php | 5 +- src/Module/Research/ResearchState.php | 8 +- .../EscapeTractorBeam/EscapeTractorBeam.php | 2 +- src/Module/Ship/Lib/AstroEntryLib.php | 4 + .../Battle/Provider/SpacecraftAttacker.php | 2 +- .../Lib/CloseCombat/BoardShipUtil.php | 2 +- .../Lib/CloseCombat/CloseCombatUtil.php | 8 +- .../Lib/Creation/SpacecraftConfigurator.php | 8 +- .../Spacecraft/Lib/Crew/SpacecraftLeaver.php | 2 +- .../Lib/Crew/TroopTransferUtility.php | 2 +- .../Spacecraft/Lib/Damage/SystemDamage.php | 4 +- .../Handler/EnhanceDestroyingCrew.php | 41 ++++ .../PostFlightAstroMappingConsequence.php | 3 + .../ShowCrewmanDetails/ShowCrewmanDetails.php | 53 +++++ src/Module/Spacecraft/services.php | 4 + src/Module/Tick/Colony/ColonyTickManager.php | 2 +- .../ManagerComponent/EscapePodHandling.php | 2 +- src/Orm/Entity/Crew.php | 62 +++-- src/Orm/Entity/CrewAssignment.php | 28 ++- src/Orm/Entity/CrewAssignmentInterface.php | 9 +- src/Orm/Entity/CrewInterface.php | 25 +- src/Orm/Entity/CrewSkill.php | 83 +++++++ src/Orm/Entity/CrewSkillInterface.php | 23 ++ src/Orm/Entity/SkillEnhancement.php | 63 +++++ src/Orm/Entity/SkillEnhancementInterface.php | 17 ++ src/Orm/Entity/SkillEnhancementLog.php | 160 +++++++++++++ .../Entity/SkillEnhancementLogInterface.php | 30 +++ src/Orm/Repository/AstroEntryRepository.php | 1 - src/Orm/Repository/CrewSkillRepository.php | 39 +++ .../CrewSkillRepositoryInterface.php | 21 ++ .../SkillEnhancementLogRepository.php | 48 ++++ ...SkillEnhancementLogRepositoryInterface.php | 23 ++ .../Repository/SkillEnhancementRepository.php | 13 + .../SkillEnhancementRepositoryInterface.php | 14 ++ src/Orm/Repository/services.php | 6 + src/html/spacecraft/crewmanDetails.twig | 56 +++++ src/html/spacecraft/spacecraftDetails.twig | 18 +- testdata/Migrations/VersionTestCrew.php | 27 ++- testdata/Migrations/VersionTestCrewAssign.php | 5 +- testdata/Migrations/VersionTestCrewSkill.php | 24 ++ ...erTest__testHandle with data set 1__1.html | 4 +- ...erTest__testHandle with data set 7__1.html | 4 +- .../ShowStationTest__testHandle__1.html | 2 +- ...rTest--ALLIANCE_VIEWS-SHOW_MANAGEMENT.html | 2 +- ...trollerTest--COLONY_VIEWS-SHOW_SOCIAL.html | 4 +- ...lerTest--DATABASE_VIEWS-SHOW_TOP_CREW.html | 2 +- ...SPACECRAFT_VIEWS-SHOW_CREWMAN_DETAILS.html | 61 +++++ ...ACECRAFT_VIEWS-SHOW_SPACECRAFTDETAILS.html | 66 +++--- ...est--COMMUNICATION_VIEWS-DEFAULT_VIEW.html | 2 +- ...llerTest--MAINDESK_VIEWS-DEFAULT_VIEW.html | 2 +- ...ollerTest--STATION_VIEWS-DEFAULT_VIEW.html | 2 +- .../Crew/Skill/CreateEnhancementLogTest.php | 224 ++++++++++++++++++ .../Crew/Skill/CrewEnhancementTest.php | 123 ++++++++++ .../Crew/Skill/CrewSkillLevelEnumTest.php | 47 ++++ .../Crew/Skill/RaiseExpertiseTest.php | 179 ++++++++++++++ .../Crew/Skill/SkillEnhancementCacheTest.php | 78 ++++++ .../Provider/ManagerProviderColonyTest.php | 4 +- .../Provider/ManagerProviderStationTest.php | 4 +- .../Lib/CloseCombat/CloseCombatUtilTest.php | 70 ++---- .../Lib/Crew/TroopTransferUtilityTest.php | 4 +- .../PostFlightAstroMappingConsequenceTest.php | 22 +- 89 files changed, 2334 insertions(+), 304 deletions(-) delete mode 100644 src/Component/Crew/CrewEnum.php create mode 100644 src/Component/Crew/CrewGenderEnum.php create mode 100644 src/Component/Crew/CrewPositionEnum.php create mode 100644 src/Component/Crew/Skill/CreateEnhancementLog.php create mode 100644 src/Component/Crew/Skill/CrewEnhancemenProxy.php create mode 100644 src/Component/Crew/Skill/CrewEnhancement.php create mode 100644 src/Component/Crew/Skill/CrewEnhancementInterface.php create mode 100644 src/Component/Crew/Skill/CrewSkillLevelEnum.php create mode 100644 src/Component/Crew/Skill/RaiseExpertise.php create mode 100644 src/Component/Crew/Skill/SkillEnhancementCache.php create mode 100644 src/Component/Crew/Skill/SkillEnhancementCacheInterface.php create mode 100644 src/Component/Crew/Skill/SkillEnhancementEnum.php rename src/Migrations/Sqlite/{Version20250620190641.php => Version20250620191610.php} (97%) create mode 100644 src/Migrations/pgsql/Version20250113065603_Crew_Assignments.php create mode 100644 src/Migrations/pgsql/Version20250113075911_Skill_Level.php create mode 100644 src/Migrations/pgsql/Version20250113194515_Skill_Enhancement.php create mode 100644 src/Migrations/pgsql/Version20250114095354_Enhancement_Log.php create mode 100644 src/Migrations/pgsql/Version20250114140100.php create mode 100644 src/Migrations/pgsql/Version20250114145656.php create mode 100644 src/Module/Spacecraft/Lib/Destruction/Handler/EnhanceDestroyingCrew.php create mode 100644 src/Module/Spacecraft/View/ShowCrewmanDetails/ShowCrewmanDetails.php create mode 100644 src/Orm/Entity/CrewSkill.php create mode 100644 src/Orm/Entity/CrewSkillInterface.php create mode 100644 src/Orm/Entity/SkillEnhancement.php create mode 100644 src/Orm/Entity/SkillEnhancementInterface.php create mode 100644 src/Orm/Entity/SkillEnhancementLog.php create mode 100644 src/Orm/Entity/SkillEnhancementLogInterface.php create mode 100644 src/Orm/Repository/CrewSkillRepository.php create mode 100644 src/Orm/Repository/CrewSkillRepositoryInterface.php create mode 100644 src/Orm/Repository/SkillEnhancementLogRepository.php create mode 100644 src/Orm/Repository/SkillEnhancementLogRepositoryInterface.php create mode 100644 src/Orm/Repository/SkillEnhancementRepository.php create mode 100644 src/Orm/Repository/SkillEnhancementRepositoryInterface.php create mode 100644 src/html/spacecraft/crewmanDetails.twig create mode 100644 testdata/Migrations/VersionTestCrewSkill.php create mode 100644 tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_CREWMAN_DETAILS.html create mode 100644 tests/unit/Component/Crew/Skill/CreateEnhancementLogTest.php create mode 100644 tests/unit/Component/Crew/Skill/CrewEnhancementTest.php create mode 100644 tests/unit/Component/Crew/Skill/CrewSkillLevelEnumTest.php create mode 100644 tests/unit/Component/Crew/Skill/RaiseExpertiseTest.php create mode 100644 tests/unit/Component/Crew/Skill/SkillEnhancementCacheTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ec1fe07de..5dedc01cc 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -747,6 +747,12 @@ parameters: count: 1 path: src/Module/Crew/Lib/CrewCreator.php + - + message: '#^Cannot call method getExpertise\(\) on Stu\\Orm\\Entity\\CrewSkillInterface\|null\.$#' + identifier: method.nonObject + count: 2 + path: src/Module/Crew/Lib/CrewCreator.php + - message: '#^Cannot call method getId\(\) on Stu\\Orm\\Entity\\ShipRumpRoleInterface\|null\.$#' identifier: method.nonObject diff --git a/src/Component/Crew/CrewEnum.php b/src/Component/Crew/CrewEnum.php deleted file mode 100644 index c73e24abb..000000000 --- a/src/Component/Crew/CrewEnum.php +++ /dev/null @@ -1,63 +0,0 @@ - 10, - CrewEnum::CREW_TYPE_COMMAND => 8, - CrewEnum::CREW_TYPE_SECURITY => 20, - CrewEnum::CREW_TYPE_SCIENCE => 0, - CrewEnum::CREW_TYPE_TECHNICAL => 4, - CrewEnum::CREW_TYPE_NAVIGATION => 2, - CrewEnum::CREW_TYPE_CREWMAN => 6 - ]; - - public static function getDescription(?int $crewType): string - { - return match ($crewType) { - self::CREW_TYPE_CAPTAIN => _("Captain"), - self::CREW_TYPE_COMMAND => _("Commander"), - self::CREW_TYPE_SECURITY => _("Sicherheit"), - self::CREW_TYPE_SCIENCE => _("Wissenschaftler"), - self::CREW_TYPE_TECHNICAL => _("Ingenieur"), - self::CREW_TYPE_NAVIGATION => _("Navigator"), - self::CREW_TYPE_CREWMAN => _("Crewman"), - default => '', - }; - } -} diff --git a/src/Component/Crew/CrewGenderEnum.php b/src/Component/Crew/CrewGenderEnum.php new file mode 100644 index 000000000..8965c90c1 --- /dev/null +++ b/src/Component/Crew/CrewGenderEnum.php @@ -0,0 +1,19 @@ + "m", + self::FEMALE => "w" + }; + } +} diff --git a/src/Component/Crew/CrewPositionEnum.php b/src/Component/Crew/CrewPositionEnum.php new file mode 100644 index 000000000..e4fc8dad7 --- /dev/null +++ b/src/Component/Crew/CrewPositionEnum.php @@ -0,0 +1,56 @@ + "Captain", + self::COMMAND => "Commander", + self::SECURITY => "Sicherheit", + self::SCIENCE => "Wissenschaftler", + self::TECHNICAL => "Ingenieur", + self::NAVIGATION => "Navigator", + self::CREWMAN => "Crewman", + }; + } + + public function getFightCapability(): int + { + return match ($this) { + self::SECURITY => 20, + self::CAPTAIN => 10, + self::COMMAND => 8, + self::CREWMAN => 6, + self::TECHNICAL => 4, + self::NAVIGATION => 2, + self::SCIENCE => 0 + }; + } + + /** @return array */ + public static function getOrder(): array + { + return [ + self::CAPTAIN, + self::COMMAND, + self::SECURITY, + self::SCIENCE, + self::TECHNICAL, + self::NAVIGATION, + self::CREWMAN + ]; + } +} diff --git a/src/Component/Crew/Skill/CreateEnhancementLog.php b/src/Component/Crew/Skill/CreateEnhancementLog.php new file mode 100644 index 000000000..1018cc520 --- /dev/null +++ b/src/Component/Crew/Skill/CreateEnhancementLog.php @@ -0,0 +1,50 @@ +getCrew(); + + $log = $this->skillEnhancementLogRepository + ->prototype() + ->setUser($crew->getUser()) + ->setEnhancement($enhancement) + ->setCrewName($crew->getName()) + ->setShipName($spacecraftName) + ->setCrewId($crew->getId()) + ->setExpertise($amount) + ->setExpertiseSum($crewSkill->getExpertise()) + ->setPromotion($this->getPromotion($oldRank, $crewSkill->getRank())) + ->setTimestamp($this->stuTime->time()); + + $this->skillEnhancementLogRepository->save($log); + } + + private function getPromotion(CrewSkillLevelEnum $oldRank, CrewSkillLevelEnum $newRank): ?string + { + return $oldRank !== $newRank + ? sprintf('Beförderung %s -> %s', $oldRank->getDescription(), $newRank->getDescription()) + : null; + } +} diff --git a/src/Component/Crew/Skill/CrewEnhancemenProxy.php b/src/Component/Crew/Skill/CrewEnhancemenProxy.php new file mode 100644 index 000000000..572cd421a --- /dev/null +++ b/src/Component/Crew/Skill/CrewEnhancemenProxy.php @@ -0,0 +1,25 @@ +get(CrewEnhancementInterface::class); + + + $crewEnhancement->addExpertise($target, $trigger, $percentage); + } +} diff --git a/src/Component/Crew/Skill/CrewEnhancement.php b/src/Component/Crew/Skill/CrewEnhancement.php new file mode 100644 index 000000000..64ce0fdfa --- /dev/null +++ b/src/Component/Crew/Skill/CrewEnhancement.php @@ -0,0 +1,49 @@ +get(); + + $enhancements = $this->skillEnhancementCache->getSkillEnhancements($trigger); + if ($enhancements === null) { + return; + } + + foreach ($spacecraft->getCrewAssignments() as $crewAssignment) { + $position = $crewAssignment->getPosition(); + if ($position === null) { + continue; + } + + if (!array_key_exists($position->value, $enhancements)) { + continue; + } + + $this->raiseExpertise->raiseExpertise( + $crewAssignment->getCrew(), + $spacecraft, + $position, + $enhancements[$position->value], + $percentage + ); + } + } +} diff --git a/src/Component/Crew/Skill/CrewEnhancementInterface.php b/src/Component/Crew/Skill/CrewEnhancementInterface.php new file mode 100644 index 000000000..392a5f449 --- /dev/null +++ b/src/Component/Crew/Skill/CrewEnhancementInterface.php @@ -0,0 +1,17 @@ + 100_000, + self::COMMODORE => 50_000, + self::SENIOR_COMMANDER => 20_000, + self::COMMANDER => 10_000, + self::LIEUTENANT_COMMANDER => 5_000, + self::LIEUTENANT => 2_000, + self::JUNIOR_LIEUTENANT => 1_000, + self::ENSIGN => 300, + self::CADET => 100, + self::RECRUIT => 0 + }; + } + + public function getBonusPercentage(): int + { + return match ($this) { + self::ADMIRAL => 25, + self::COMMODORE => 20, + self::SENIOR_COMMANDER => 15, + self::COMMANDER => 12, + self::LIEUTENANT_COMMANDER => 9, + self::LIEUTENANT => 6, + self::JUNIOR_LIEUTENANT => 4, + self::ENSIGN => 2, + self::CADET => 1, + self::RECRUIT => 0 + }; + } + + public function getDescription(): string + { + return match ($this) { + self::ADMIRAL => 'Admiral', + self::COMMODORE => 'Kommodore', + self::SENIOR_COMMANDER => 'Oberkommandant', + self::COMMANDER => 'Kommandant', + self::LIEUTENANT_COMMANDER => 'Oberleutnant', + self::LIEUTENANT => 'Leutnant', + self::JUNIOR_LIEUTENANT => 'Unterleutnant', + self::ENSIGN => 'Fähnrich', + self::CADET => 'Kadett', + self::RECRUIT => 'Rekrut' + }; + } + + public static function getForExpertise(int $expertise): CrewSkillLevelEnum + { + return match (true) { + $expertise < self::CADET->getNeededExpertise() => self::RECRUIT, + $expertise < self::ENSIGN->getNeededExpertise() => self::CADET, + $expertise < self::JUNIOR_LIEUTENANT->getNeededExpertise() => self::ENSIGN, + $expertise < self::LIEUTENANT->getNeededExpertise() => self::JUNIOR_LIEUTENANT, + $expertise < self::LIEUTENANT_COMMANDER->getNeededExpertise() => self::LIEUTENANT, + $expertise < self::COMMANDER->getNeededExpertise() => self::LIEUTENANT_COMMANDER, + $expertise < self::SENIOR_COMMANDER->getNeededExpertise() => self::COMMANDER, + $expertise < self::COMMODORE->getNeededExpertise() => self::SENIOR_COMMANDER, + $expertise < self::ADMIRAL->getNeededExpertise() => self::COMMODORE, + default => self::ADMIRAL + }; + } +} diff --git a/src/Component/Crew/Skill/RaiseExpertise.php b/src/Component/Crew/Skill/RaiseExpertise.php new file mode 100644 index 000000000..fc9a0e735 --- /dev/null +++ b/src/Component/Crew/Skill/RaiseExpertise.php @@ -0,0 +1,61 @@ +getSkills(); + + /** @var null|CrewSkillInterface */ + $skill = $skills->get($position->value); + if ($skill === null) { + $skill = $this->crewSkillRepository + ->prototype() + ->setCrew($crew) + ->setPosition($position); + + $skills->set($position->value, $skill); + } + + $oldRank = $skill->getRank(); + $amount = (int)ceil($enhancement->getExpertise() * $percentage / 100); + $skill->increaseExpertise($amount); + $this->crewSkillRepository->save($skill); + + if ($skill->getRank()->getNeededExpertise() > $oldRank->getNeededExpertise()) { + $crew->setRank($skill->getRank()); + $this->crewRepository->save($crew); + } + + $this->createEnhancementLog->createEnhancementLog( + $skill, + $spacecraft->getName(), + $enhancement, + $amount, + $oldRank + ); + } +} diff --git a/src/Component/Crew/Skill/SkillEnhancementCache.php b/src/Component/Crew/Skill/SkillEnhancementCache.php new file mode 100644 index 000000000..185e189e0 --- /dev/null +++ b/src/Component/Crew/Skill/SkillEnhancementCache.php @@ -0,0 +1,41 @@ +>|null */ + private ?array $enhancements = null; + + public function __construct(private SkillEnhancementRepositoryInterface $skillEnhancementRepository) {} + + /** @return array */ + public function getSkillEnhancements(SkillEnhancementEnum $enhancementType): ?array + { + if ($this->enhancements === null) { + $this->enhancements = []; + + $enhancements = $this->skillEnhancementRepository->findAll(); + foreach ($enhancements as $enhancement) { + $type = $enhancement->getType()->value; + $position = $enhancement->getPosition()->value; + if (!array_key_exists($type, $this->enhancements)) { + $this->enhancements[$type] = []; + } + + $this->enhancements[$type][$position] = $enhancement; + } + } + + if (!array_key_exists($enhancementType->value, $this->enhancements)) { + return null; + } + + return $this->enhancements[$enhancementType->value]; + } +} diff --git a/src/Component/Crew/Skill/SkillEnhancementCacheInterface.php b/src/Component/Crew/Skill/SkillEnhancementCacheInterface.php new file mode 100644 index 000000000..817a96746 --- /dev/null +++ b/src/Component/Crew/Skill/SkillEnhancementCacheInterface.php @@ -0,0 +1,13 @@ + */ + public function getSkillEnhancements(SkillEnhancementEnum $type): ?array; +} diff --git a/src/Component/Crew/Skill/SkillEnhancementEnum.php b/src/Component/Crew/Skill/SkillEnhancementEnum.php new file mode 100644 index 000000000..4b2236045 --- /dev/null +++ b/src/Component/Crew/Skill/SkillEnhancementEnum.php @@ -0,0 +1,13 @@ + autowire(CrewCountRetriever::class), + RaiseExpertise::class => autowire(RaiseExpertise::class), + CreateEnhancementLog::class => autowire(CreateEnhancementLog::class), + CrewEnhancementInterface::class => autowire(CrewEnhancement::class), + SkillEnhancementCacheInterface::class => autowire(SkillEnhancementCache::class) ]; diff --git a/src/Component/Spacecraft/Repair/RepairUtil.php b/src/Component/Spacecraft/Repair/RepairUtil.php index d9352ed1f..c40a440a8 100644 --- a/src/Component/Spacecraft/Repair/RepairUtil.php +++ b/src/Component/Spacecraft/Repair/RepairUtil.php @@ -8,7 +8,7 @@ use RuntimeException; use Stu\Component\Building\BuildingFunctionEnum; use Stu\Component\Colony\ColonyFunctionManagerInterface; -use Stu\Component\Crew\CrewEnum; +use Stu\Component\Crew\CrewPositionEnum; use Stu\Component\Spacecraft\SpacecraftStateEnum; use Stu\Lib\Transfer\Storage\StorageManagerInterface; use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum; @@ -229,7 +229,7 @@ public function determineFreeEngineerCount(SpacecraftInterface $ship): int $nextNumber = 1; foreach ($ship->getCrewAssignments() as $shipCrew) { if ( - $shipCrew->getSlot() === CrewEnum::CREW_TYPE_TECHNICAL + $shipCrew->getPosition() === CrewPositionEnum::TECHNICAL //&& $shipCrew->getRepairTask() === null ) { $engineerOptions[] = $nextNumber; diff --git a/src/Component/Spacecraft/System/Type/TroopQuartersShipSystem.php b/src/Component/Spacecraft/System/Type/TroopQuartersShipSystem.php index a98630247..21dc27729 100644 --- a/src/Component/Spacecraft/System/Type/TroopQuartersShipSystem.php +++ b/src/Component/Spacecraft/System/Type/TroopQuartersShipSystem.php @@ -27,7 +27,7 @@ public function getSystemType(): SpacecraftSystemTypeEnum public function handleDestruction(SpacecraftWrapperInterface $wrapper): void { foreach ($wrapper->get()->getCrewAssignments() as $crewAssignment) { - if ($crewAssignment->getSlot() === null) { + if ($crewAssignment->getPosition() === null) { $this->crewRepository->delete($crewAssignment->getCrew()); } } diff --git a/src/Lib/SpacecraftManagement/Provider/ManagerProviderColony.php b/src/Lib/SpacecraftManagement/Provider/ManagerProviderColony.php index b3a769803..85da129ec 100644 --- a/src/Lib/SpacecraftManagement/Provider/ManagerProviderColony.php +++ b/src/Lib/SpacecraftManagement/Provider/ManagerProviderColony.php @@ -60,7 +60,7 @@ public function getFreeCrewAmount(): int #[Override] public function addCrewAssignment(SpacecraftInterface $spacecraft, int $amount): void { - $this->crewCreator->createCrewAssignment($spacecraft, $this->colony, $amount); + $this->crewCreator->createCrewAssignments($spacecraft, $this->colony, $amount); } #[Override] diff --git a/src/Lib/SpacecraftManagement/Provider/ManagerProviderStation.php b/src/Lib/SpacecraftManagement/Provider/ManagerProviderStation.php index 0ece9a677..e89fc0ec2 100644 --- a/src/Lib/SpacecraftManagement/Provider/ManagerProviderStation.php +++ b/src/Lib/SpacecraftManagement/Provider/ManagerProviderStation.php @@ -83,7 +83,7 @@ public function getFreeCrewAmount(): int #[Override] public function addCrewAssignment(SpacecraftInterface $spacecraft, int $amount): void { - $this->crewCreator->createCrewAssignment($spacecraft, $this->wrapper->get(), $amount); + $this->crewCreator->createCrewAssignments($spacecraft, $this->wrapper->get(), $amount); } #[Override] diff --git a/src/Migrations/Sqlite/Version20250620190641.php b/src/Migrations/Sqlite/Version20250620191610.php similarity index 97% rename from src/Migrations/Sqlite/Version20250620190641.php rename to src/Migrations/Sqlite/Version20250620191610.php index 0e2c1ffaf..697fec513 100644 --- a/src/Migrations/Sqlite/Version20250620190641.php +++ b/src/Migrations/Sqlite/Version20250620191610.php @@ -10,7 +10,7 @@ /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20250620190641 extends AbstractMigration +final class Version20250620191610 extends AbstractMigration { public function getDescription(): string { @@ -456,7 +456,7 @@ public function up(Schema $schema): void CREATE INDEX user_pair_idx ON stu_contactlist (user_id, recipient) SQL); $this->addSql(<<<'SQL' - CREATE TABLE stu_crew (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, type SMALLINT NOT NULL, gender SMALLINT NOT NULL, name VARCHAR(255) NOT NULL, user_id INTEGER NOT NULL, race_id INTEGER NOT NULL, CONSTRAINT FK_167BE6E46E59D40D FOREIGN KEY (race_id) REFERENCES stu_crew_race (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_167BE6E4A76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE) + CREATE TABLE stu_crew (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, rank VARCHAR(255) NOT NULL, gender SMALLINT NOT NULL, name VARCHAR(255) NOT NULL, user_id INTEGER NOT NULL, race_id INTEGER NOT NULL, CONSTRAINT FK_167BE6E46E59D40D FOREIGN KEY (race_id) REFERENCES stu_crew_race (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_167BE6E4A76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE) SQL); $this->addSql(<<<'SQL' CREATE INDEX IDX_167BE6E46E59D40D ON stu_crew (race_id) @@ -465,7 +465,7 @@ public function up(Schema $schema): void CREATE INDEX IDX_167BE6E4A76ED395 ON stu_crew (user_id) SQL); $this->addSql(<<<'SQL' - CREATE TABLE stu_crew_assign (slot SMALLINT DEFAULT NULL, crew_id INTEGER NOT NULL, spacecraft_id INTEGER DEFAULT NULL, colony_id INTEGER DEFAULT NULL, tradepost_id INTEGER DEFAULT NULL, user_id INTEGER NOT NULL, repair_task_id INTEGER DEFAULT NULL, PRIMARY KEY(crew_id), CONSTRAINT FK_4793ED245FE259F6 FOREIGN KEY (crew_id) REFERENCES stu_crew (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED241C6AF6FD FOREIGN KEY (spacecraft_id) REFERENCES stu_spacecraft (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED2496ADBADE FOREIGN KEY (colony_id) REFERENCES stu_colonies (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED248B935ABD FOREIGN KEY (tradepost_id) REFERENCES stu_trade_posts (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED24A76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED24130D5415 FOREIGN KEY (repair_task_id) REFERENCES stu_repair_task (id) NOT DEFERRABLE INITIALLY IMMEDIATE) + CREATE TABLE stu_crew_assign (position SMALLINT DEFAULT NULL, crew_id INTEGER NOT NULL, spacecraft_id INTEGER DEFAULT NULL, colony_id INTEGER DEFAULT NULL, tradepost_id INTEGER DEFAULT NULL, user_id INTEGER NOT NULL, repair_task_id INTEGER DEFAULT NULL, PRIMARY KEY(crew_id), CONSTRAINT FK_4793ED245FE259F6 FOREIGN KEY (crew_id) REFERENCES stu_crew (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED241C6AF6FD FOREIGN KEY (spacecraft_id) REFERENCES stu_spacecraft (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED2496ADBADE FOREIGN KEY (colony_id) REFERENCES stu_colonies (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED248B935ABD FOREIGN KEY (tradepost_id) REFERENCES stu_trade_posts (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED24A76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4793ED24130D5415 FOREIGN KEY (repair_task_id) REFERENCES stu_repair_task (id) NOT DEFERRABLE INITIALLY IMMEDIATE) SQL); $this->addSql(<<<'SQL' CREATE INDEX IDX_4793ED241C6AF6FD ON stu_crew_assign (spacecraft_id) @@ -488,6 +488,12 @@ public function up(Schema $schema): void $this->addSql(<<<'SQL' CREATE INDEX IDX_ED3686294448F8DA ON stu_crew_race (faction_id) SQL); + $this->addSql(<<<'SQL' + CREATE TABLE stu_crew_skill (crew_id INTEGER NOT NULL, position SMALLINT NOT NULL, expertise INTEGER NOT NULL, PRIMARY KEY(crew_id, position), CONSTRAINT FK_5AD19B5F5FE259F6 FOREIGN KEY (crew_id) REFERENCES stu_crew (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_5AD19B5F5FE259F6 ON stu_crew_skill (crew_id) + SQL); $this->addSql(<<<'SQL' CREATE TABLE stu_crew_training (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, user_id INTEGER NOT NULL, colony_id INTEGER NOT NULL, CONSTRAINT FK_E25756B996ADBADE FOREIGN KEY (colony_id) REFERENCES stu_colonies (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_E25756B9A76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE) SQL); @@ -1208,6 +1214,21 @@ public function up(Schema $schema): void $this->addSql(<<<'SQL' CREATE INDEX shipyard_shipqueue_finish_date_idx ON stu_shipyard_shipqueue (finish_date) SQL); + $this->addSql(<<<'SQL' + CREATE TABLE stu_skill_enhancement (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, type SMALLINT NOT NULL, position SMALLINT NOT NULL, expertise INTEGER NOT NULL, description VARCHAR(255) NOT NULL) + SQL); + $this->addSql(<<<'SQL' + CREATE UNIQUE INDEX skill_enhancement_unique_idx ON stu_skill_enhancement (type, position) + SQL); + $this->addSql(<<<'SQL' + CREATE TABLE stu_skill_enhancement_log (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, user_id INTEGER NOT NULL, enhancement_id INTEGER NOT NULL, crew_id INTEGER NOT NULL, crew_name VARCHAR(255) NOT NULL, promotion VARCHAR(255) DEFAULT NULL, ship_name VARCHAR(255) NOT NULL, expertise INTEGER NOT NULL, expertise_sum INTEGER NOT NULL, date INTEGER NOT NULL, CONSTRAINT FK_73B42DBBA76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_73B42DBB49186B17 FOREIGN KEY (enhancement_id) REFERENCES stu_skill_enhancement (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_73B42DBBA76ED395 ON stu_skill_enhancement_log (user_id) + SQL); + $this->addSql(<<<'SQL' + CREATE INDEX IDX_73B42DBB49186B17 ON stu_skill_enhancement_log (enhancement_id) + SQL); $this->addSql(<<<'SQL' CREATE TABLE stu_spacecraft (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, user_id INTEGER NOT NULL, rump_id INTEGER NOT NULL, plan_id INTEGER DEFAULT NULL, name VARCHAR(255) NOT NULL, max_huelle INTEGER NOT NULL, max_schilde INTEGER NOT NULL, tractored_ship_id INTEGER DEFAULT NULL, holding_web_id INTEGER DEFAULT NULL, database_id INTEGER DEFAULT NULL, location_id INTEGER NOT NULL, type VARCHAR(255) NOT NULL, CONSTRAINT FK_4BD20E2EEE54A42E FOREIGN KEY (tractored_ship_id) REFERENCES stu_ship (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4BD20E2E73D3801E FOREIGN KEY (holding_web_id) REFERENCES stu_tholian_web (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4BD20E2EA76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4BD20E2E2EE98D4C FOREIGN KEY (rump_id) REFERENCES stu_rump (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4BD20E2EE899029B FOREIGN KEY (plan_id) REFERENCES stu_buildplan (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_4BD20E2E64D218E FOREIGN KEY (location_id) REFERENCES stu_location (id) NOT DEFERRABLE INITIALLY IMMEDIATE) SQL); @@ -1810,6 +1831,9 @@ public function down(Schema $schema): void $this->addSql(<<<'SQL' DROP TABLE stu_crew_race SQL); + $this->addSql(<<<'SQL' + DROP TABLE stu_crew_skill + SQL); $this->addSql(<<<'SQL' DROP TABLE stu_crew_training SQL); @@ -2053,6 +2077,12 @@ public function down(Schema $schema): void $this->addSql(<<<'SQL' DROP TABLE stu_shipyard_shipqueue SQL); + $this->addSql(<<<'SQL' + DROP TABLE stu_skill_enhancement + SQL); + $this->addSql(<<<'SQL' + DROP TABLE stu_skill_enhancement_log + SQL); $this->addSql(<<<'SQL' DROP TABLE stu_spacecraft SQL); diff --git a/src/Migrations/pgsql/Version20250113065603_Crew_Assignments.php b/src/Migrations/pgsql/Version20250113065603_Crew_Assignments.php new file mode 100644 index 000000000..120eed1f8 --- /dev/null +++ b/src/Migrations/pgsql/Version20250113065603_Crew_Assignments.php @@ -0,0 +1,26 @@ +addSql('ALTER TABLE stu_crew_assign RENAME COLUMN slot TO position'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE stu_crew_assign RENAME COLUMN position TO slot'); + } +} diff --git a/src/Migrations/pgsql/Version20250113075911_Skill_Level.php b/src/Migrations/pgsql/Version20250113075911_Skill_Level.php new file mode 100644 index 000000000..094df10f9 --- /dev/null +++ b/src/Migrations/pgsql/Version20250113075911_Skill_Level.php @@ -0,0 +1,29 @@ +addSql('CREATE TABLE stu_crew_skill (crew_id INT NOT NULL, position SMALLINT NOT NULL, expertise INT NOT NULL, PRIMARY KEY(crew_id, position))'); + $this->addSql('CREATE INDEX IDX_5AD19B5F5FE259F6 ON stu_crew_skill (crew_id)'); + $this->addSql('ALTER TABLE stu_crew_skill ADD CONSTRAINT FK_5AD19B5F5FE259F6 FOREIGN KEY (crew_id) REFERENCES stu_crew (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE stu_crew_skill DROP CONSTRAINT FK_5AD19B5F5FE259F6'); + $this->addSql('DROP TABLE stu_crew_skill'); + } +} diff --git a/src/Migrations/pgsql/Version20250113194515_Skill_Enhancement.php b/src/Migrations/pgsql/Version20250113194515_Skill_Enhancement.php new file mode 100644 index 000000000..f6b8adfda --- /dev/null +++ b/src/Migrations/pgsql/Version20250113194515_Skill_Enhancement.php @@ -0,0 +1,27 @@ +addSql('CREATE TABLE stu_skill_enhancement (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, type SMALLINT NOT NULL, position SMALLINT NOT NULL, expertise INT NOT NULL, description VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE UNIQUE INDEX skill_enhancement_unique_idx ON stu_skill_enhancement (type, position)'); + } + + public function down(Schema $schema): void + { + $this->addSql('DROP TABLE stu_skill_enhancement'); + } +} diff --git a/src/Migrations/pgsql/Version20250114095354_Enhancement_Log.php b/src/Migrations/pgsql/Version20250114095354_Enhancement_Log.php new file mode 100644 index 000000000..a4a6ff007 --- /dev/null +++ b/src/Migrations/pgsql/Version20250114095354_Enhancement_Log.php @@ -0,0 +1,32 @@ +addSql('CREATE TABLE stu_skill_enhancement_log (id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, user_id INT NOT NULL, enhancement_id INT NOT NULL, crew_name VARCHAR(255) NOT NULL, promotion VARCHAR(255) DEFAULT NULL, ship_name VARCHAR(255) NOT NULL, expertise INT NOT NULL, expertise_sum INT NOT NULL, date INT NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_73B42DBBA76ED395 ON stu_skill_enhancement_log (user_id)'); + $this->addSql('CREATE INDEX IDX_73B42DBB49186B17 ON stu_skill_enhancement_log (enhancement_id)'); + $this->addSql('ALTER TABLE stu_skill_enhancement_log ADD CONSTRAINT FK_73B42DBBA76ED395 FOREIGN KEY (user_id) REFERENCES stu_user (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE stu_skill_enhancement_log ADD CONSTRAINT FK_73B42DBB49186B17 FOREIGN KEY (enhancement_id) REFERENCES stu_skill_enhancement (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE stu_skill_enhancement_log DROP CONSTRAINT FK_73B42DBBA76ED395'); + $this->addSql('ALTER TABLE stu_skill_enhancement_log DROP CONSTRAINT FK_73B42DBB49186B17'); + $this->addSql('DROP TABLE stu_skill_enhancement_log'); + } +} diff --git a/src/Migrations/pgsql/Version20250114140100.php b/src/Migrations/pgsql/Version20250114140100.php new file mode 100644 index 000000000..15c11922f --- /dev/null +++ b/src/Migrations/pgsql/Version20250114140100.php @@ -0,0 +1,30 @@ +addSql('ALTER TABLE stu_crew ADD rank VARCHAR(255) DEFAULT NULL'); + $this->addSql(sprintf('UPDATE stu_crew set rank = \'RECRUIT\'')); + $this->addSql('ALTER TABLE stu_crew ALTER rank SET NOT NULL'); + $this->addSql('ALTER TABLE stu_crew DROP type'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE stu_crew ADD type SMALLINT NOT NULL'); + $this->addSql('ALTER TABLE stu_crew DROP rank'); + } +} diff --git a/src/Migrations/pgsql/Version20250114145656.php b/src/Migrations/pgsql/Version20250114145656.php new file mode 100644 index 000000000..b88d09df5 --- /dev/null +++ b/src/Migrations/pgsql/Version20250114145656.php @@ -0,0 +1,26 @@ +addSql('ALTER TABLE stu_skill_enhancement_log ADD crew_id INT NOT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE stu_skill_enhancement_log DROP crew_id'); + } +} diff --git a/src/Migrations/pgsql/Version20250203092918.php b/src/Migrations/pgsql/Version20250203092918.php index e7bc694c4..0437d4e87 100644 --- a/src/Migrations/pgsql/Version20250203092918.php +++ b/src/Migrations/pgsql/Version20250203092918.php @@ -16,7 +16,6 @@ public function getDescription(): string public function up(Schema $schema): void { - // this up() migration is auto-generated, please modify it to your needs $this->addSql('ALTER INDEX ship_crew_spacecraft_idx RENAME TO IDX_4793ED241C6AF6FD'); $this->addSql('ALTER INDEX ship_crew_colony_idx RENAME TO IDX_4793ED2496ADBADE'); $this->addSql('ALTER INDEX ship_crew_tradepost_idx RENAME TO IDX_4793ED248B935ABD'); diff --git a/src/Module/Colony/Action/StartAirfieldShip/StartAirfieldShip.php b/src/Module/Colony/Action/StartAirfieldShip/StartAirfieldShip.php index d2bbb803d..98bfa7787 100644 --- a/src/Module/Colony/Action/StartAirfieldShip/StartAirfieldShip.php +++ b/src/Module/Colony/Action/StartAirfieldShip/StartAirfieldShip.php @@ -124,7 +124,7 @@ public function handle(GameControllerInterface $game): void $wrapper = $shipConfigurator->finishConfiguration(); $ship = $wrapper->get(); - $this->crewCreator->createCrewAssignment($ship, $colony); + $this->crewCreator->createCrewAssignments($ship, $colony); $defaultTorpedoType = $hangar->getDefaultTorpedoType(); if ($defaultTorpedoType !== null && $storage->containsKey($defaultTorpedoType->getCommodityId())) { diff --git a/src/Module/Crew/Lib/CrewCreator.php b/src/Module/Crew/Lib/CrewCreator.php index 8c889bbca..e6025919e 100644 --- a/src/Module/Crew/Lib/CrewCreator.php +++ b/src/Module/Crew/Lib/CrewCreator.php @@ -6,16 +6,17 @@ use Override; use RuntimeException; -use Stu\Component\Crew\CrewEnum; +use Stu\Component\Crew\CrewGenderEnum; use Stu\Component\Crew\CrewOriginException; +use Stu\Component\Crew\CrewPositionEnum; use Stu\Orm\Entity\ColonyInterface; use Stu\Orm\Entity\CrewAssignmentInterface; use Stu\Orm\Entity\SpacecraftInterface; +use Stu\Orm\Entity\UserInterface; use Stu\Orm\Repository\CrewRaceRepositoryInterface; use Stu\Orm\Repository\CrewRepositoryInterface; use Stu\Orm\Repository\CrewAssignmentRepositoryInterface; use Stu\Orm\Repository\ShipRumpCategoryRoleCrewRepositoryInterface; -use Stu\Orm\Repository\UserRepositoryInterface; final class CrewCreator implements CrewCreatorInterface { @@ -23,19 +24,12 @@ public function __construct( private CrewRaceRepositoryInterface $crewRaceRepository, private ShipRumpCategoryRoleCrewRepositoryInterface $shipRumpCategoryRoleCrewRepository, private CrewAssignmentRepositoryInterface $shipCrewRepository, - private CrewRepositoryInterface $crewRepository, - private UserRepositoryInterface $userRepository + private CrewRepositoryInterface $crewRepository ) {} #[Override] - public function create(int $userId, ?ColonyInterface $colony = null): CrewAssignmentInterface + public function create(UserInterface $user, ?ColonyInterface $colony = null): CrewAssignmentInterface { - $user = $this->userRepository->find($userId); - - if ($user === null) { - throw new RuntimeException('user not found1'); - } - $arr = []; $raceList = $this->crewRaceRepository->getByFaction((int)$user->getFactionId()); foreach ($raceList as $obj) { @@ -51,7 +45,7 @@ function (&$value) use ($obj): void { } $race = $this->crewRaceRepository->find($arr[array_rand($arr)]); - $gender = random_int(1, 100) > $race->getMaleRatio() ? CrewEnum::CREW_GENDER_FEMALE : CrewEnum::CREW_GENDER_MALE; + $gender = random_int(1, 100) > $race->getMaleRatio() ? CrewGenderEnum::FEMALE : CrewGenderEnum::MALE; $crew = $this->crewRepository->prototype(); @@ -59,7 +53,6 @@ function (&$value) use ($obj): void { $crew->setName('Crew'); $crew->setRace($race); $crew->setGender($gender); - $crew->setType(CrewEnum::CREW_TYPE_CREWMAN); $this->crewRepository->save($crew); $crewAssignment = $this->shipCrewRepository->prototype(); @@ -75,16 +68,16 @@ function (&$value) use ($obj): void { } #[Override] - public function createCrewAssignment( + public function createCrewAssignments( SpacecraftInterface $spacecraft, ColonyInterface|SpacecraftInterface $crewProvider, ?int $amount = null ): void { $crewToSetup = $amount ?? $spacecraft->getBuildPlan()->getCrew(); - foreach (CrewEnum::CREW_ORDER as $crewType) { + foreach (CrewPositionEnum::getOrder() as $position) { $createdcount = 1; - $slot = $crewType == CrewEnum::CREW_TYPE_CREWMAN ? 'getJob6Crew' : 'getJob' . $crewType . 'Crew'; + $slot = $position === CrewPositionEnum::CREWMAN ? 'getJob6Crew' : 'getJob' . $position->value . 'Crew'; $config = $this->shipRumpCategoryRoleCrewRepository->getByShipRumpCategoryAndRole( $spacecraft->getRump()->getShipRumpCategory()->getId(), $spacecraft->getRump()->getShipRumpRole()->getId() @@ -97,11 +90,11 @@ public function createCrewAssignment( )); } - while ($crewToSetup > 0 && ($crewType == CrewEnum::CREW_TYPE_CREWMAN || $createdcount <= $config->$slot())) { + while ($crewToSetup > 0 && ($position === CrewPositionEnum::CREWMAN || $createdcount <= $config->$slot())) { $createdcount++; $crewToSetup--; - $crewAssignment = $this->getCrewByType($crewType, $crewProvider); + $crewAssignment = $this->getCrewByType($position, $crewProvider); if ($crewAssignment === null) { $crewAssignment = $this->getCrew($crewProvider); } @@ -113,9 +106,8 @@ public function createCrewAssignment( $crewAssignment->setSpacecraft($spacecraft); $crewAssignment->setColony(null); $crewAssignment->setTradepost(null); - //TODO set both ship and crew user $crewAssignment->setUser($spacecraft->getUser()); - $crewAssignment->setSlot($crewType); + $crewAssignment->setPosition($position); $spacecraft->getCrewAssignments()->add($crewAssignment); @@ -125,26 +117,35 @@ public function createCrewAssignment( } private function getCrewByType( - int $crewType, + CrewPositionEnum $position, ColonyInterface|SpacecraftInterface $crewProvider ): ?CrewAssignmentInterface { - foreach ($crewProvider->getCrewAssignments() as $crewAssignment) { - $crew = $crewAssignment->getCrew(); - if ($crew->getType() === $crewType) { - $crewProvider->getCrewAssignments()->removeElement($crewAssignment); + $filteredCrewAssignments = $crewProvider + ->getCrewAssignments() + ->filter(fn(CrewAssignmentInterface $assignment): bool => $assignment->getCrew()->isSkilledAt($position)) + ->toArray(); - return $crewAssignment; - } + if ($filteredCrewAssignments === []) { + return null; } - return null; + usort( + $filteredCrewAssignments, + fn(CrewAssignmentInterface $a, CrewAssignmentInterface $b): int => + $b->getCrew()->getSkills()->get($position->value)->getExpertise() - $a->getCrew()->getSkills()->get($position->value)->getExpertise() + ); + + + $crewAssignment = current($filteredCrewAssignments); + $crewProvider->getCrewAssignments()->removeElement($crewAssignment); + + return $crewAssignment; } private function getCrew(ColonyInterface|SpacecraftInterface $crewProvider): ?CrewAssignmentInterface { $crewAssignments = $crewProvider->getCrewAssignments(); - if ($crewAssignments->isEmpty()) { return null; } diff --git a/src/Module/Crew/Lib/CrewCreatorInterface.php b/src/Module/Crew/Lib/CrewCreatorInterface.php index 8c0d3d507..edf5c2251 100644 --- a/src/Module/Crew/Lib/CrewCreatorInterface.php +++ b/src/Module/Crew/Lib/CrewCreatorInterface.php @@ -5,10 +5,11 @@ use Stu\Orm\Entity\ColonyInterface; use Stu\Orm\Entity\CrewAssignmentInterface; use Stu\Orm\Entity\SpacecraftInterface; +use Stu\Orm\Entity\UserInterface; interface CrewCreatorInterface { - public function create(int $userId, ?ColonyInterface $colony = null): CrewAssignmentInterface; + public function create(UserInterface $user, ?ColonyInterface $colony = null): CrewAssignmentInterface; - public function createCrewAssignment(SpacecraftInterface $spacecraft, ColonyInterface|SpacecraftInterface $crewProvider, ?int $amount = null): void; + public function createCrewAssignments(SpacecraftInterface $spacecraft, ColonyInterface|SpacecraftInterface $crewProvider, ?int $amount = null): void; } diff --git a/src/Module/Research/ResearchState.php b/src/Module/Research/ResearchState.php index f612693c7..5d5fb4aac 100644 --- a/src/Module/Research/ResearchState.php +++ b/src/Module/Research/ResearchState.php @@ -76,7 +76,9 @@ private function createRewardShip(ResearchedInterface $state): void $plan = $state->getResearch()->getRewardBuildplan(); /** @var ColonyInterface */ $colony = $userColonies->first(); - $wrapper = $this->shipCreator->createBy($userId, $plan->getRump()->getId(), $plan->getId()) + + $wrapper = $this->shipCreator + ->createBy($userId, $plan->getRump()->getId(), $plan->getId()) ->setLocation($colony->getStarsystemMap()) ->maxOutSystems() ->finishConfiguration(); @@ -89,10 +91,10 @@ private function createRewardShip(ResearchedInterface $state): void $this->shipRepository->save($ship); for ($j = 1; $j <= $plan->getCrew(); $j++) { - $this->crewCreator->create($userId, $colony); + $this->crewCreator->create($state->getUser(), $colony); } $this->entityManager->flush(); //TODO really neccessary? - $this->crewCreator->createCrewAssignment($ship, $colony); + $this->crewCreator->createCrewAssignments($ship, $colony); $txt = sprintf(_("Als Belohnung für den Abschluss der Forschung wurde dir ein Schiff vom Typ %s überstellt"), $plan->getRump()->getName()); diff --git a/src/Module/Ship/Action/EscapeTractorBeam/EscapeTractorBeam.php b/src/Module/Ship/Action/EscapeTractorBeam/EscapeTractorBeam.php index 2c474f41e..23d91e642 100644 --- a/src/Module/Ship/Action/EscapeTractorBeam/EscapeTractorBeam.php +++ b/src/Module/Ship/Action/EscapeTractorBeam/EscapeTractorBeam.php @@ -173,7 +173,7 @@ private function sufferHullDamage( $otherUserId = $tractoringSpacecraft->getUser()->getId(); $shipName = $ship->getName(); - $game->addInformation(_('Der Fluchtversuch ist fehlgeschlagen:')); + $game->addInformation('Der Fluchtversuch ist fehlgeschlagen:'); $this->applyDamage->damage(new DamageWrapper((int) ceil($ship->getMaxHull() * random_int(10, 25) / 100)), $wrapper, $game); diff --git a/src/Module/Ship/Lib/AstroEntryLib.php b/src/Module/Ship/Lib/AstroEntryLib.php index 6b1dc5e7c..2e0787875 100644 --- a/src/Module/Ship/Lib/AstroEntryLib.php +++ b/src/Module/Ship/Lib/AstroEntryLib.php @@ -6,6 +6,8 @@ use Override; use RuntimeException; +use Stu\Component\Crew\Skill\CrewEnhancemenProxy; +use Stu\Component\Crew\Skill\SkillEnhancementEnum; use Stu\Component\Ship\AstronomicalMappingEnum; use Stu\Component\Spacecraft\SpacecraftStateEnum; use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface; @@ -65,6 +67,8 @@ public function finish(ShipWrapperInterface $wrapper): void $entry->setState(AstronomicalMappingEnum::DONE); $entry->setAstroStartTurn(null); $this->astroEntryRepository->save($entry); + + CrewEnhancemenProxy::addExpertise($ship, SkillEnhancementEnum::FINISH_ASTRO_MAPPING); } #[Override] diff --git a/src/Module/Spacecraft/Lib/Battle/Provider/SpacecraftAttacker.php b/src/Module/Spacecraft/Lib/Battle/Provider/SpacecraftAttacker.php index d311a829d..c29445bf8 100644 --- a/src/Module/Spacecraft/Lib/Battle/Provider/SpacecraftAttacker.php +++ b/src/Module/Spacecraft/Lib/Battle/Provider/SpacecraftAttacker.php @@ -101,7 +101,7 @@ public function getUserId(): int return $this->get()->getUser()->getId(); } - private function get(): SpacecraftInterface + public function get(): SpacecraftInterface { return $this->wrapper->get(); } diff --git a/src/Module/Spacecraft/Lib/CloseCombat/BoardShipUtil.php b/src/Module/Spacecraft/Lib/CloseCombat/BoardShipUtil.php index bc6cc3ec5..367b526ef 100644 --- a/src/Module/Spacecraft/Lib/CloseCombat/BoardShipUtil.php +++ b/src/Module/Spacecraft/Lib/CloseCombat/BoardShipUtil.php @@ -53,7 +53,7 @@ public function cycleKillRound( $message = $this->messageFactory->createMessage($ship->getUser()->getId(), $killedCrewAssignment->getUser()->getId()); $message->add(sprintf( '%s %s des Spielers %s von der %s wurde im Kampf getötet.', - $killedCrewAssignment->getCrew()->getTypeDescription(), + $killedCrewAssignment->getCrew()->getRank()->getDescription(), $killedCrewAssignment->getCrew()->getName(), $isDeathOnDefenderSide ? $target->getUser()->getName() : $ship->getUser()->getName(), $isDeathOnDefenderSide ? $target->getName() : $ship->getName() diff --git a/src/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtil.php b/src/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtil.php index bcaa0c21f..90f592977 100644 --- a/src/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtil.php +++ b/src/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtil.php @@ -5,7 +5,6 @@ namespace Stu\Module\Spacecraft\Lib\CloseCombat; use Override; -use Stu\Component\Crew\CrewEnum; use Stu\Orm\Entity\FactionInterface; use Stu\Orm\Entity\CrewAssignmentInterface; use Stu\Orm\Entity\SpacecraftInterface; @@ -22,8 +21,7 @@ public function getCombatGroup(SpacecraftInterface $spacecraft): array usort( $crewArray, fn(CrewAssignmentInterface $a, CrewAssignmentInterface $b): int - => CrewEnum::CREW_FIGHT_CAPABILITIES[$b->getCrew()->getType()] - <=> CrewEnum::CREW_FIGHT_CAPABILITIES[$a->getCrew()->getType()] + => $b->getFightCapability() <=> $a->getFightCapability() ); return array_slice($crewArray, 0, self::MAX_CREWMAN_PER_COMBAT); @@ -36,8 +34,8 @@ public function getCombatValue(array $combatGroup, FactionInterface $faction): i return array_reduce( $combatGroup, - fn(int $value, CrewAssignmentInterface $shipCrew): int - => $value + CrewEnum::CREW_FIGHT_CAPABILITIES[$shipCrew->getCrew()->getType()] * $factionCombatScore, + fn(int $value, CrewAssignmentInterface $crewAssignment): int + => $value + $crewAssignment->getFightCapability() * $factionCombatScore, 0 ); } diff --git a/src/Module/Spacecraft/Lib/Creation/SpacecraftConfigurator.php b/src/Module/Spacecraft/Lib/Creation/SpacecraftConfigurator.php index 24c00452d..fb4a5fbd1 100644 --- a/src/Module/Spacecraft/Lib/Creation/SpacecraftConfigurator.php +++ b/src/Module/Spacecraft/Lib/Creation/SpacecraftConfigurator.php @@ -12,6 +12,7 @@ use Stu\Module\Spacecraft\Lib\ActivatorDeactivatorHelperInterface; use Stu\Module\Spacecraft\Lib\Torpedo\ShipTorpedoManagerInterface; use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface; +use Stu\Orm\Entity\ColonyInterface; use Stu\Orm\Entity\LocationInterface; use Stu\Orm\Repository\CrewAssignmentRepositoryInterface; use Stu\Orm\Repository\SpacecraftRepositoryInterface; @@ -114,15 +115,16 @@ public function maxOutSystems(): SpacecraftConfiguratorInterface } #[Override] - public function createCrew(?int $amount = null): SpacecraftConfiguratorInterface + public function createCrew(?int $amount = null, ?ColonyInterface $colony = null): SpacecraftConfiguratorInterface { + //TODO consolidate roles and stuff like in CrewCreator $ship = $this->wrapper->get(); $buildplan = $ship->getBuildplan(); if ($buildplan !== null) { $crewAmount = $amount !== null && $amount >= 0 ? $amount : $buildplan->getCrew(); for ($j = 1; $j <= $crewAmount; $j++) { - $crewAssignment = $this->crewCreator->create($ship->getUser()->getId()); + $crewAssignment = $this->crewCreator->create($ship->getUser(), $colony); $crewAssignment->setSpacecraft($ship); $this->shipCrewRepository->save($crewAssignment); @@ -136,6 +138,8 @@ public function createCrew(?int $amount = null): SpacecraftConfiguratorInterface return $this; } + //TODO public function transferCrewFromCOlony... + #[Override] public function setAlertState(SpacecraftAlertStateEnum $alertState): SpacecraftConfiguratorInterface { diff --git a/src/Module/Spacecraft/Lib/Crew/SpacecraftLeaver.php b/src/Module/Spacecraft/Lib/Crew/SpacecraftLeaver.php index 7a01a7e5e..2d9ed2f0e 100644 --- a/src/Module/Spacecraft/Lib/Crew/SpacecraftLeaver.php +++ b/src/Module/Spacecraft/Lib/Crew/SpacecraftLeaver.php @@ -63,7 +63,7 @@ private function escapeIntoPods(SpacecraftInterface $spacecraft): void $crewList = $spacecraft->getCrewAssignments(); foreach ($crewList as $shipCrew) { $shipCrew->setSpacecraft($pods); - $shipCrew->setSlot(null); + $shipCrew->setPosition(null); $this->shipCrewRepository->save($shipCrew); } } diff --git a/src/Module/Spacecraft/Lib/Crew/TroopTransferUtility.php b/src/Module/Spacecraft/Lib/Crew/TroopTransferUtility.php index 828f2e610..08b00754b 100644 --- a/src/Module/Spacecraft/Lib/Crew/TroopTransferUtility.php +++ b/src/Module/Spacecraft/Lib/Crew/TroopTransferUtility.php @@ -74,7 +74,7 @@ public function assignCrew(CrewAssignmentInterface $crewAssignment, EntityWithCr // TODO create CrewSlotAssignment $crewAssignment->clearAssignment() ->assign($target) - ->setSlot(null); + ->setPosition(null); $target->getCrewAssignments()->add($crewAssignment); diff --git a/src/Module/Spacecraft/Lib/Damage/SystemDamage.php b/src/Module/Spacecraft/Lib/Damage/SystemDamage.php index e0e051b1f..3087fbc92 100644 --- a/src/Module/Spacecraft/Lib/Damage/SystemDamage.php +++ b/src/Module/Spacecraft/Lib/Damage/SystemDamage.php @@ -53,9 +53,9 @@ public function destroyRandomShipSystem(SpacecraftWrapperInterface $wrapper, Dam $system = $healthySystems[0]; $system->setStatus(0); $system->setMode(SpacecraftSystemModeEnum::MODE_OFF); - $this->spacecraftSystemManager->handleDestroyedSystem($wrapper, $healthySystems[0]->getSystemType()); + $this->spacecraftSystemManager->handleDestroyedSystem($wrapper, $system->getSystemType()); - return $healthySystems[0]->getSystemType()->getDescription(); + return $system->getSystemType()->getDescription(); } #[Override] diff --git a/src/Module/Spacecraft/Lib/Destruction/Handler/EnhanceDestroyingCrew.php b/src/Module/Spacecraft/Lib/Destruction/Handler/EnhanceDestroyingCrew.php new file mode 100644 index 000000000..e5ab4363d --- /dev/null +++ b/src/Module/Spacecraft/Lib/Destruction/Handler/EnhanceDestroyingCrew.php @@ -0,0 +1,41 @@ +get()->getRump()->getPrestige(); + if ( + $destroyedPrestige > 0 + && $destroyer instanceof SpacecraftAttacker + ) { + + CrewEnhancemenProxy::addExpertise( + $destroyer->get(), + SkillEnhancementEnum::SPACECRAFT_DESTRUCTION, + min(200, (int)ceil($destroyedPrestige * 100 / abs($destroyer->get()->getRump()->getPrestige()))) + ); + } + } +} diff --git a/src/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequence.php b/src/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequence.php index 39e8d289c..749fb7efc 100644 --- a/src/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequence.php +++ b/src/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequence.php @@ -5,6 +5,8 @@ namespace Stu\Module\Spacecraft\Lib\Movement\Component\Consequence\PostFlight; use Override; +use Stu\Component\Crew\Skill\CrewEnhancemenProxy; +use Stu\Component\Crew\Skill\SkillEnhancementEnum; use Stu\Component\Ship\AstronomicalMappingEnum; use Stu\Component\Spacecraft\SpacecraftStateEnum; use Stu\Module\Prestige\Lib\CreatePrestigeLogInterface; @@ -84,6 +86,7 @@ protected function triggerSpecific( } $this->createPrestigeLog($ship); + CrewEnhancemenProxy::addExpertise($ship, SkillEnhancementEnum::REACH_ASTRO_WAYPOINT); } } diff --git a/src/Module/Spacecraft/View/ShowCrewmanDetails/ShowCrewmanDetails.php b/src/Module/Spacecraft/View/ShowCrewmanDetails/ShowCrewmanDetails.php new file mode 100644 index 000000000..0b63a510b --- /dev/null +++ b/src/Module/Spacecraft/View/ShowCrewmanDetails/ShowCrewmanDetails.php @@ -0,0 +1,53 @@ +setMacroInAjaxWindow('html/entityNotAvailable.twig'); + + $crewAssignment = $this->crewAssignmentRepository->find(request::indInt('id')); + if ($crewAssignment === null) { + return; + } + + $crew = $crewAssignment->getCrew(); + if ($crew->getUser() !== $game->getUser()) { + return; + } + + $game->setPageTitle('Crewman Details'); + $game->setViewTemplate('html/spacecraft/crewmanDetails.twig'); + + $game->setTemplateVar('CREW_ASSIGNMENT', $crewAssignment); + $game->setTemplateVar('COUNT', $count); + $game->setTemplateVar('LOGS', $this->skillEnhancementLogRepository->getForCrewman($crew)); + } +} diff --git a/src/Module/Spacecraft/services.php b/src/Module/Spacecraft/services.php index 2c6f7b475..a11c65916 100644 --- a/src/Module/Spacecraft/services.php +++ b/src/Module/Spacecraft/services.php @@ -159,6 +159,7 @@ use Stu\Module\Spacecraft\Lib\Destruction\Handler\ClearTractoringBeam; use Stu\Module\Spacecraft\Lib\Destruction\Handler\ColonizationShipCheck; use Stu\Module\Spacecraft\Lib\Destruction\Handler\CrewEvacuation; +use Stu\Module\Spacecraft\Lib\Destruction\Handler\EnhanceDestroyingCrew; use Stu\Module\Spacecraft\Lib\Destruction\Handler\HistoryEntryCreation; use Stu\Module\Spacecraft\Lib\Destruction\Handler\LeaveIntactModules; use Stu\Module\Spacecraft\Lib\Destruction\Handler\PrestigeGain; @@ -253,6 +254,7 @@ use Stu\Module\Spacecraft\Lib\Ui\ShipUiFactory; use Stu\Module\Spacecraft\Lib\Ui\ShipUiFactoryInterface; use Stu\Module\Spacecraft\Lib\Ui\StateIconAndTitle; +use Stu\Module\Spacecraft\View\ShowCrewmanDetails\ShowCrewmanDetails; use Stu\Module\Spacecraft\View\ShowSystemSettings\AggregrationSystemSettings; use Stu\Module\Spacecraft\View\ShowSystemSettings\BussardCollectorSystemSettings; use Stu\Module\Spacecraft\View\ShowSystemSettings\ShowSystemSettings; @@ -388,6 +390,7 @@ autowire(LeaveIntactModules::class), autowire(ClearTractoringBeam::class), autowire(ColonizationShipCheck::class), + autowire(EnhanceDestroyingCrew::class), autowire(PrestigeGain::class), autowire(ResetTrackerDevices::class), autowire(TradepostDestruction::class), @@ -471,6 +474,7 @@ ShowAlertLevel::VIEW_IDENTIFIER => autowire(ShowAlertLevel::class), ShowAnalyseBuoy::VIEW_IDENTIFIER => autowire(ShowAnalyseBuoy::class), ShowColonyScan::VIEW_IDENTIFIER => autowire(ShowColonyScan::class), + ShowCrewmanDetails::VIEW_IDENTIFIER => autowire(ShowCrewmanDetails::class), ShowEpsTransfer::VIEW_IDENTIFIER => autowire(ShowEpsTransfer::class), ShowInformation::VIEW_IDENTIFIER => autowire(ShowInformation::class), ShowLSSFilter::VIEW_IDENTIFIER => autowire(ShowLSSFilter::class), diff --git a/src/Module/Tick/Colony/ColonyTickManager.php b/src/Module/Tick/Colony/ColonyTickManager.php index 5d6f93907..14d13c963 100644 --- a/src/Module/Tick/Colony/ColonyTickManager.php +++ b/src/Module/Tick/Colony/ColonyTickManager.php @@ -118,7 +118,7 @@ private function proceedCrewTraining(int $batchGroup, int $batchGroupCount): voi if (!$this->colonyFunctionManager->hasActiveFunction($colony, BuildingFunctionEnum::ACADEMY)) { continue; } - $this->crewCreator->create($obj->getUserId(), $colony); + $this->crewCreator->create($obj->getUser(), $colony); $this->crewTrainingRepository->delete($obj); $user[$obj->getUserId()]++; diff --git a/src/Module/Tick/Spacecraft/ManagerComponent/EscapePodHandling.php b/src/Module/Tick/Spacecraft/ManagerComponent/EscapePodHandling.php index f1c56f1d6..63ef1cabc 100644 --- a/src/Module/Tick/Spacecraft/ManagerComponent/EscapePodHandling.php +++ b/src/Module/Tick/Spacecraft/ManagerComponent/EscapePodHandling.php @@ -76,7 +76,7 @@ private function transferOwnCrewToColony(ShipInterface $escapePod, ColonyInterfa $count++; $crewAssignment->setSpacecraft(null); - $crewAssignment->setSlot(null); + $crewAssignment->setPosition(null); $crewAssignment->setColony($colony); $escapePod->getCrewAssignments()->removeElement($crewAssignment); $colony->getCrewAssignments()->add($crewAssignment); diff --git a/src/Orm/Entity/Crew.php b/src/Orm/Entity/Crew.php index 234e66c8d..204090c8d 100644 --- a/src/Orm/Entity/Crew.php +++ b/src/Orm/Entity/Crew.php @@ -4,15 +4,20 @@ namespace Stu\Orm\Entity; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\GeneratedValue; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\JoinColumn; use Doctrine\ORM\Mapping\ManyToOne; +use Doctrine\ORM\Mapping\OneToMany; use Doctrine\ORM\Mapping\Table; use Override; -use Stu\Component\Crew\CrewEnum; +use Stu\Component\Crew\CrewGenderEnum; +use Stu\Component\Crew\CrewPositionEnum; +use Stu\Component\Crew\Skill\CrewSkillLevelEnum; use Stu\Orm\Repository\CrewRepository; #[Table(name: 'stu_crew')] @@ -24,11 +29,11 @@ class Crew implements CrewInterface #[GeneratedValue(strategy: 'IDENTITY')] private int $id; - #[Column(type: 'smallint')] - private int $type = 0; + #[Column(type: 'string', enumType: CrewSkillLevelEnum::class)] + private CrewSkillLevelEnum $rank = CrewSkillLevelEnum::RECRUIT; - #[Column(type: 'smallint')] - private int $gender = 0; + #[Column(type: 'smallint', enumType: CrewGenderEnum::class)] + private CrewGenderEnum $gender = CrewGenderEnum::MALE; #[Column(type: 'string')] private string $name = ''; @@ -47,6 +52,17 @@ class Crew implements CrewInterface #[JoinColumn(name: 'user_id', referencedColumnName: 'id', onDelete: 'CASCADE')] private UserInterface $user; + /** + * @var ArrayCollection + */ + #[OneToMany(targetEntity: 'CrewSkill', mappedBy: 'crew', indexBy: 'position', fetch: 'EXTRA_LAZY')] + private Collection $skills; + + public function __construct() + { + $this->skills = new ArrayCollection(); + } + #[Override] public function getId(): int { @@ -54,27 +70,27 @@ public function getId(): int } #[Override] - public function getType(): int + public function getRank(): CrewSkillLevelEnum { - return $this->type; + return $this->rank; } #[Override] - public function setType(int $type): CrewInterface + public function setRank(CrewSkillLevelEnum $rank): CrewInterface { - $this->type = $type; + $this->rank = $rank; return $this; } #[Override] - public function getGender(): int + public function getGender(): CrewGenderEnum { return $this->gender; } #[Override] - public function setGender(int $gender): CrewInterface + public function setGender(CrewGenderEnum $gender): CrewInterface { $this->gender = $gender; @@ -129,32 +145,28 @@ public function setRaceId(int $raceId): CrewInterface } #[Override] - public function getGenderShort(): string + public function getRace(): CrewRaceInterface { - if ($this->getGender() == CrewEnum::CREW_GENDER_MALE) { - return 'm'; - } - return 'w'; + return $this->race; } #[Override] - public function getTypeDescription(): string + public function setRace(CrewRaceInterface $crewRace): CrewInterface { - return CrewEnum::getDescription($this->getType()); + $this->race = $crewRace; + + return $this; } - #[Override] - public function getRace(): CrewRaceInterface + public function getSkills(): Collection { - return $this->race; + return $this->skills; } #[Override] - public function setRace(CrewRaceInterface $crewRace): CrewInterface + public function isSkilledAt(CrewPositionEnum $position): bool { - $this->race = $crewRace; - - return $this; + return $this->skills->containsKey($position->value); } #[Override] diff --git a/src/Orm/Entity/CrewAssignment.php b/src/Orm/Entity/CrewAssignment.php index acbb73290..3852cb09b 100644 --- a/src/Orm/Entity/CrewAssignment.php +++ b/src/Orm/Entity/CrewAssignment.php @@ -12,7 +12,7 @@ use Doctrine\ORM\Mapping\OneToOne; use Doctrine\ORM\Mapping\Table; use Override; -use Stu\Component\Crew\CrewEnum; +use Stu\Component\Crew\CrewPositionEnum; use Stu\Module\Spacecraft\Lib\Crew\EntityWithCrewAssignmentsInterface; use Stu\Orm\Repository\CrewAssignmentRepository; @@ -25,8 +25,8 @@ class CrewAssignment implements CrewAssignmentInterface #[JoinColumn(name: 'crew_id', referencedColumnName: 'id', onDelete: 'CASCADE')] private CrewInterface $crew; - #[Column(type: 'smallint', nullable: true)] - private ?int $slot = null; + #[Column(type: 'smallint', enumType: CrewPositionEnum::class, nullable: true)] + private ?CrewPositionEnum $position = null; #[ManyToOne(targetEntity: 'Spacecraft')] #[JoinColumn(name: 'spacecraft_id', referencedColumnName: 'id', onDelete: 'CASCADE')] @@ -49,25 +49,19 @@ class CrewAssignment implements CrewAssignmentInterface private ?RepairTaskInterface $repairTask = null; #[Override] - public function getSlot(): ?int + public function getPosition(): ?CrewPositionEnum { - return $this->slot; + return $this->position ?? CrewPositionEnum::CREWMAN; } #[Override] - public function setSlot(?int $slot): CrewAssignmentInterface + public function setPosition(?CrewPositionEnum $position): CrewAssignmentInterface { - $this->slot = $slot; + $this->position = $position; return $this; } - #[Override] - public function getPosition(): string - { - return CrewEnum::getDescription($this->getSlot()); - } - #[Override] public function getUser(): UserInterface { @@ -149,6 +143,14 @@ public function setTradepost(?TradePostInterface $tradepost): CrewAssignmentInte return $this; } + #[Override] + public function getFightCapability(): int + { + $position = $this->getPosition() ?? CrewPositionEnum::CREWMAN; + + return $position->getFightCapability(); + } + #[Override] public function clearAssignment(): CrewAssignmentInterface { diff --git a/src/Orm/Entity/CrewAssignmentInterface.php b/src/Orm/Entity/CrewAssignmentInterface.php index 104d47188..d3d2ca8ba 100644 --- a/src/Orm/Entity/CrewAssignmentInterface.php +++ b/src/Orm/Entity/CrewAssignmentInterface.php @@ -2,15 +2,14 @@ namespace Stu\Orm\Entity; +use Stu\Component\Crew\CrewPositionEnum; use Stu\Module\Spacecraft\Lib\Crew\EntityWithCrewAssignmentsInterface; interface CrewAssignmentInterface { - public function getSlot(): ?int; + public function getPosition(): ?CrewPositionEnum; - public function setSlot(?int $slot): CrewAssignmentInterface; - - public function getPosition(): string; + public function setPosition(?CrewPositionEnum $position): CrewAssignmentInterface; public function getUser(): UserInterface; @@ -36,6 +35,8 @@ public function getTradepost(): ?TradePostInterface; public function setTradepost(?TradePostInterface $tradepost): CrewAssignmentInterface; + public function getFightCapability(): int; + public function clearAssignment(): CrewAssignmentInterface; public function assign(EntityWithCrewAssignmentsInterface $target): CrewAssignmentInterface; diff --git a/src/Orm/Entity/CrewInterface.php b/src/Orm/Entity/CrewInterface.php index 8ab19e888..218919cc7 100644 --- a/src/Orm/Entity/CrewInterface.php +++ b/src/Orm/Entity/CrewInterface.php @@ -2,17 +2,23 @@ namespace Stu\Orm\Entity; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +use Stu\Component\Crew\CrewGenderEnum; +use Stu\Component\Crew\CrewPositionEnum; +use Stu\Component\Crew\Skill\CrewSkillLevelEnum; + interface CrewInterface { public function getId(): int; - public function getType(): int; + public function getRank(): CrewSkillLevelEnum; - public function setType(int $type): CrewInterface; + public function setRank(CrewSkillLevelEnum $rank): CrewInterface; - public function getGender(): int; + public function getGender(): CrewGenderEnum; - public function setGender(int $gender): CrewInterface; + public function setGender(CrewGenderEnum $gender): CrewInterface; public function getName(): string; @@ -26,11 +32,14 @@ public function getRaceId(): int; public function setRaceId(int $raceId): CrewInterface; - public function getGenderShort(): string; - - public function getTypeDescription(): string; - public function getRace(): CrewRaceInterface; public function setRace(CrewRaceInterface $crewRace): CrewInterface; + + /** + * @return ArrayCollection + */ + public function getSkills(): Collection; + + public function isSkilledAt(CrewPositionEnum $position): bool; } diff --git a/src/Orm/Entity/CrewSkill.php b/src/Orm/Entity/CrewSkill.php new file mode 100644 index 000000000..c6b1c7a66 --- /dev/null +++ b/src/Orm/Entity/CrewSkill.php @@ -0,0 +1,83 @@ +position; + } + + #[Override] + public function setPosition(CrewPositionEnum $position): CrewSkillInterface + { + $this->position = $position; + + return $this; + } + + #[Override] + public function getCrew(): CrewInterface + { + return $this->crew; + } + + #[Override] + public function setCrew(CrewInterface $crew): CrewSkillInterface + { + $this->crew = $crew; + $this->crew_id = $crew->getId(); + + return $this; + } + + #[Override] + public function increaseExpertise(int $amount): void + { + $this->expertise += $amount; + } + + #[Override] + public function getExpertise(): int + { + return $this->expertise; + } + + #[Override] + public function getRank(): CrewSkillLevelEnum + { + return CrewSkillLevelEnum::getForExpertise($this->expertise); + } +} diff --git a/src/Orm/Entity/CrewSkillInterface.php b/src/Orm/Entity/CrewSkillInterface.php new file mode 100644 index 000000000..40681eb20 --- /dev/null +++ b/src/Orm/Entity/CrewSkillInterface.php @@ -0,0 +1,23 @@ +type; + } + + #[Override] + public function getPosition(): CrewPositionEnum + { + return $this->position; + } + + #[Override] + public function getExpertise(): int + { + return $this->expertise; + } + + #[Override] + public function getDescription(): string + { + return $this->description; + } +} diff --git a/src/Orm/Entity/SkillEnhancementInterface.php b/src/Orm/Entity/SkillEnhancementInterface.php new file mode 100644 index 000000000..6b50611c8 --- /dev/null +++ b/src/Orm/Entity/SkillEnhancementInterface.php @@ -0,0 +1,17 @@ +user = $user; + + return $this; + } + + #[Override] + public function setEnhancement(SkillEnhancementInterface $enhancement): SkillEnhancementLogInterface + { + $this->enhancement = $enhancement; + + return $this; + } + + #[Override] + public function setCrewName(string $crewName): SkillEnhancementLogInterface + { + $this->crew_name = $crewName; + + return $this; + } + + #[Override] + public function setShipName(string $shipName): SkillEnhancementLogInterface + { + $this->ship_name = $shipName; + + return $this; + } + + #[Override] + public function setCrewId(int $crewId): SkillEnhancementLogInterface + { + $this->crew_id = $crewId; + + return $this; + } + + #[Override] + public function getPromotion(): ?string + { + return $this->promotion; + } + + #[Override] + public function setPromotion(?string $text): SkillEnhancementLogInterface + { + $this->promotion = $text; + + return $this; + } + + #[Override] + public function setExpertise(int $amount): SkillEnhancementLogInterface + { + $this->expertise = $amount; + + return $this; + } + + #[Override] + public function setExpertiseSum(int $sum): SkillEnhancementLogInterface + { + $this->expertise_sum = $sum; + + return $this; + } + + #[Override] + public function getTimestamp(): int + { + return $this->date; + } + + #[Override] + public function setTimestamp(int $date): SkillEnhancementLogInterface + { + $this->date = $date; + + return $this; + } + + #[Override] + public function __toString(): string + { + return sprintf( + '%s (%s) von der %s steigt auf %d (+%d) Expertise%s für %s', + $this->crew_name, + $this->enhancement->getPosition()->getDescription(), + $this->ship_name, + $this->expertise_sum, + $this->expertise, + $this->promotion === null ? sprintf(' (Rang %s)', CrewSkillLevelEnum::getForExpertise($this->expertise)->getDescription()) : '', + $this->enhancement->getDescription() + ); + } +} diff --git a/src/Orm/Entity/SkillEnhancementLogInterface.php b/src/Orm/Entity/SkillEnhancementLogInterface.php new file mode 100644 index 000000000..15e070257 --- /dev/null +++ b/src/Orm/Entity/SkillEnhancementLogInterface.php @@ -0,0 +1,30 @@ +getEntityManager(); $em->remove($entry); - $em->flush(); //TODO really neccessary? } diff --git a/src/Orm/Repository/CrewSkillRepository.php b/src/Orm/Repository/CrewSkillRepository.php new file mode 100644 index 000000000..2e043e448 --- /dev/null +++ b/src/Orm/Repository/CrewSkillRepository.php @@ -0,0 +1,39 @@ + + */ +final class CrewSkillRepository extends EntityRepository implements CrewSkillRepositoryInterface +{ + + #[Override] + public function prototype(): CrewSkillInterface + { + return new CrewSkill(); + } + + #[Override] + public function save(CrewSkillInterface $crewSkill): void + { + $em = $this->getEntityManager(); + + $em->persist($crewSkill); + } + + #[Override] + public function delete(CrewSkillInterface $crewSkill): void + { + $em = $this->getEntityManager(); + + $em->remove($crewSkill); + } +} diff --git a/src/Orm/Repository/CrewSkillRepositoryInterface.php b/src/Orm/Repository/CrewSkillRepositoryInterface.php new file mode 100644 index 000000000..46d5de20e --- /dev/null +++ b/src/Orm/Repository/CrewSkillRepositoryInterface.php @@ -0,0 +1,21 @@ + + * + * @method null|CrewSkillInterface find(integer $id) + */ +interface CrewSkillRepositoryInterface extends ObjectRepository +{ + public function prototype(): CrewSkillInterface; + + public function save(CrewSkillInterface $post): void; + + public function delete(CrewSkillInterface $post): void; +} diff --git a/src/Orm/Repository/SkillEnhancementLogRepository.php b/src/Orm/Repository/SkillEnhancementLogRepository.php new file mode 100644 index 000000000..dd19fb0d9 --- /dev/null +++ b/src/Orm/Repository/SkillEnhancementLogRepository.php @@ -0,0 +1,48 @@ + + */ +final class SkillEnhancementLogRepository extends EntityRepository implements SkillEnhancementLogRepositoryInterface +{ + + #[Override] + public function prototype(): SkillEnhancementLogInterface + { + return new SkillEnhancementLog(); + } + + #[Override] + public function save(SkillEnhancementLogInterface $post): void + { + $em = $this->getEntityManager(); + + $em->persist($post); + } + + #[Override] + public function getForCrewman(CrewInterface $crew): array + { + return $this->getEntityManager() + ->createQuery( + sprintf( + 'SELECT el FROM %s el + WHERE el.crew_id = :crewId + ORDER BY el.id DESC', + SkillEnhancementLog::class + ) + ) + ->setParameter('crewId', $crew->getId()) + ->getResult(); + } +} diff --git a/src/Orm/Repository/SkillEnhancementLogRepositoryInterface.php b/src/Orm/Repository/SkillEnhancementLogRepositoryInterface.php new file mode 100644 index 000000000..e26c0397f --- /dev/null +++ b/src/Orm/Repository/SkillEnhancementLogRepositoryInterface.php @@ -0,0 +1,23 @@ + + * + * @method array findAll() + */ +interface SkillEnhancementLogRepositoryInterface extends ObjectRepository +{ + public function prototype(): SkillEnhancementLogInterface; + + public function save(SkillEnhancementLogInterface $log): void; + + /** @return array */ + public function getForCrewman(CrewInterface $crew): array; +} diff --git a/src/Orm/Repository/SkillEnhancementRepository.php b/src/Orm/Repository/SkillEnhancementRepository.php new file mode 100644 index 000000000..f59fd4a22 --- /dev/null +++ b/src/Orm/Repository/SkillEnhancementRepository.php @@ -0,0 +1,13 @@ + + */ +final class SkillEnhancementRepository extends EntityRepository implements SkillEnhancementRepositoryInterface {} diff --git a/src/Orm/Repository/SkillEnhancementRepositoryInterface.php b/src/Orm/Repository/SkillEnhancementRepositoryInterface.php new file mode 100644 index 000000000..b08fc6938 --- /dev/null +++ b/src/Orm/Repository/SkillEnhancementRepositoryInterface.php @@ -0,0 +1,14 @@ + + * + * @method array findAll() + */ +interface SkillEnhancementRepositoryInterface extends ObjectRepository {} diff --git a/src/Orm/Repository/services.php b/src/Orm/Repository/services.php index 6de0450d6..3ebddd3a9 100644 --- a/src/Orm/Repository/services.php +++ b/src/Orm/Repository/services.php @@ -109,6 +109,7 @@ use Stu\Orm\Entity\Ship; use Stu\Orm\Entity\SpacecraftBuildplan; use Stu\Orm\Entity\CrewAssignment; +use Stu\Orm\Entity\CrewSkill; use Stu\Orm\Entity\ShipLog; use Stu\Orm\Entity\ShipRumpBuildingFunction; use Stu\Orm\Entity\ShipRumpCategory; @@ -121,6 +122,8 @@ use Stu\Orm\Entity\ShipRumpUser; use Stu\Orm\Entity\ShipTakeover; use Stu\Orm\Entity\ShipyardShipQueue; +use Stu\Orm\Entity\SkillEnhancement; +use Stu\Orm\Entity\SkillEnhancementLog; use Stu\Orm\Entity\Spacecraft; use Stu\Orm\Entity\SpacecraftEmergency; use Stu\Orm\Entity\SpacecraftRump; @@ -204,6 +207,7 @@ ColonyScanRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(ColonyScan::class), CrewRaceRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(CrewRace::class), CrewRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(Crew::class), + CrewSkillRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(CrewSkill::class), CrewTrainingRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(CrewTraining::class), DatabaseCategoryRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(DatabaseCategory::class), DatabaseCategoryAwardRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(DatabaseCategoryAward::class), @@ -283,6 +287,8 @@ SpacecraftSystemRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(SpacecraftSystem::class), ShipTakeoverRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(ShipTakeover::class), ShipyardShipQueueRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(ShipyardShipQueue::class), + SkillEnhancementRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(SkillEnhancement::class), + SkillEnhancementLogRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(SkillEnhancementLog::class), SpacecraftRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(Spacecraft::class), SpacecraftEmergencyRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(SpacecraftEmergency::class), StarSystemMapRepositoryInterface::class => fn(ContainerInterface $c): EntityRepository => $c->get(EntityManagerInterface::class)->getRepository(StarSystemMap::class), diff --git a/src/html/spacecraft/crewmanDetails.twig b/src/html/spacecraft/crewmanDetails.twig new file mode 100644 index 000000000..bab598b64 --- /dev/null +++ b/src/html/spacecraft/crewmanDetails.twig @@ -0,0 +1,56 @@ +{% set crew = CREW_ASSIGNMENT.getCrew %} +{% set skills = crew.getSkills %} +
+
+ {% if skills|length > 0 %} +
+
+
Skills
+
+ {% for skill in crew.getSkills %} +
+
{{ skill.getPosition.getDescription }}
+
+ {{ skill.getRank.getDescription }} ({{ skill.getExpertise }}) +
+
+ {% endfor %} +
+
+
+ {% endif %} +
+
Anzahl
+
+ + + +
+
+
+ + + + + + {% if LOGS %} + {% for entry in LOGS %} + {% set promotion = entry.getPromotion %} + + {% if promotion %} + + {% endif %} + {% set colspan = promotion ? 1 : 2 %} + + + + {% endfor %} + {% else %} + + + + {% endif %} +
EintragDatum
{{ promotion }}{{ entry.__toString|bbcode }}{{ entry.getTimestamp|stuDateTime }}
Keine Einträge vorhanden
+
+
+
diff --git a/src/html/spacecraft/spacecraftDetails.twig b/src/html/spacecraft/spacecraftDetails.twig index 1cad7e791..81a656e11 100644 --- a/src/html/spacecraft/spacecraftDetails.twig +++ b/src/html/spacecraft/spacecraftDetails.twig @@ -101,31 +101,31 @@ Rang {% for data in SHIP.getCrewAssignments %} + {% set id = data.getCrew.getId %} {% set crew = data.getCrew %} - {% set crewId = data.getId %} + src="assets/crew/{{ crew.getRace.getGfxPath }}/{{ crew.getGender.getShort }}/1_{{ data.getPosition.value }}.png" /> {% if data.getCrew.getUser != SHIP.getUser %} * - - + + {% endif %} -
{{ data.getPosition }}
+
{{ data.getPosition.getDescription }}
{% set CREW = crew %} {% include 'html/ship/crew/crewSlot.twig' %} - -
{{ data.getCrew.getTypeDescription }}
+ +
{{ crew.getRank.getDescription }}
{% endfor %} diff --git a/testdata/Migrations/VersionTestCrew.php b/testdata/Migrations/VersionTestCrew.php index b93c7b1c3..f38d5a7f1 100644 --- a/testdata/Migrations/VersionTestCrew.php +++ b/testdata/Migrations/VersionTestCrew.php @@ -16,19 +16,20 @@ public function getDescription(): string public function up(Schema $schema): void { - $this->addSql('INSERT INTO stu_crew (id, type, gender, name, user_id, race_id) - VALUES (2, 6, 1, \'Crew\', 101, 3), - (3, 6, 1, \'Crew\', 101, 2), - (4, 6, 1, \'Crew\', 101, 3), - (5, 6, 2, \'Crew\', 101, 3), - (6, 6, 1, \'Crew\', 101, 12), - (7, 6, 1, \'Crew\', 101, 3), - (8, 6, 1, \'Crew\', 101, 2), - (9, 6, 2, \'Crew\', 101, 3), - (10, 6, 1, \'Crew\', 101, 2), - (11, 6, 1, \'Crew\', 101, 3), - (12, 6, 2, \'Crew\', 101, 1), - (13, 6, 2, \'Crew\', 101, 1); + $this->addSql('INSERT INTO stu_crew (id, rank, gender, name, user_id, race_id) + VALUES (2, \'RECRUIT\', 1, \'Crew\', 101, 3), + (3, \'RECRUIT\', 1, \'Crew\', 101, 2), + (4, \'RECRUIT\', 1, \'Crew\', 101, 3), + (5, \'RECRUIT\', 2, \'Crew\', 101, 3), + (6, \'RECRUIT\', 1, \'Crew\', 101, 12), + (7, \'RECRUIT\', 1, \'Crew\', 101, 3), + (8, \'RECRUIT\', 1, \'Crew\', 101, 2), + (9, \'RECRUIT\', 2, \'Crew\', 101, 3), + (10, \'RECRUIT\', 1, \'Crew\', 101, 2), + (11, \'RECRUIT\', 1, \'Crew\', 101, 3), + (12, \'RECRUIT\', 2, \'Crew\', 101, 1), + (13, \'RECRUIT\', 2, \'Crew\', 101, 1), + (42, \'RECRUIT\', 2, \'Crew\', 101, 1); '); } } diff --git a/testdata/Migrations/VersionTestCrewAssign.php b/testdata/Migrations/VersionTestCrewAssign.php index a26d97dd1..7aa8bdfa7 100644 --- a/testdata/Migrations/VersionTestCrewAssign.php +++ b/testdata/Migrations/VersionTestCrewAssign.php @@ -16,7 +16,7 @@ public function getDescription(): string public function up(Schema $schema): void { - $this->addSql('INSERT INTO stu_crew_assign (spacecraft_id, crew_id, slot, user_id, repair_task_id, colony_id, tradepost_id) + $this->addSql('INSERT INTO stu_crew_assign (spacecraft_id, crew_id, position, user_id, repair_task_id, colony_id, tradepost_id) VALUES (42, 2, NULL, 101, NULL, NULL, NULL), (42, 3, NULL, 101, NULL, NULL, NULL), (42, 4, NULL, 101, NULL, NULL, NULL), @@ -28,7 +28,8 @@ public function up(Schema $schema): void (42, 10, NULL, 101, NULL, NULL, NULL), (42, 11, NULL, 101, NULL, NULL, NULL), (42, 12, NULL, 101, NULL, NULL, NULL), - (43, 13, NULL, 101, NULL, NULL, NULL); + (43, 13, NULL, 101, NULL, NULL, NULL), + (43, 42, NULL, 101, NULL, NULL, NULL); '); } } diff --git a/testdata/Migrations/VersionTestCrewSkill.php b/testdata/Migrations/VersionTestCrewSkill.php new file mode 100644 index 000000000..a1a5f5fb8 --- /dev/null +++ b/testdata/Migrations/VersionTestCrewSkill.php @@ -0,0 +1,24 @@ +addSql('INSERT INTO stu_crew_skill (crew_id,"position",expertise) + VALUES (42,1,89), + (42,7,178); + '); + } +} diff --git a/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 1__1.html b/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 1__1.html index 8a531c971..565651929 100644 --- a/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 1__1.html +++ b/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 1__1.html @@ -51,7 +51,7 @@ @@ -92,7 +92,7 @@
- + 0
- +
diff --git a/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 7__1.html b/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 7__1.html index aa60679ad..254c56a9b 100644 --- a/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 7__1.html +++ b/tests/inttest/html/Game/__snapshots__/ShowTransferTest__testHandle with data set 7__1.html @@ -60,7 +60,7 @@ - + 0 @@ -101,7 +101,7 @@ - + diff --git a/tests/inttest/html/Spacecraft/__snapshots__/ShowStationTest__testHandle__1.html b/tests/inttest/html/Spacecraft/__snapshots__/ShowStationTest__testHandle__1.html index e2868e841..69c84ed77 100644 --- a/tests/inttest/html/Spacecraft/__snapshots__/ShowStationTest__testHandle__1.html +++ b/tests/inttest/html/Spacecraft/__snapshots__/ShowStationTest__testHandle__1.html @@ -318,7 +318,7 @@ - 1 + 2 (1,25) diff --git a/tests/inttest/html/__snapshots__/AllViewControllerTest--ALLIANCE_VIEWS-SHOW_MANAGEMENT.html b/tests/inttest/html/__snapshots__/AllViewControllerTest--ALLIANCE_VIEWS-SHOW_MANAGEMENT.html index 15bfe0375..38a5c0e97 100644 --- a/tests/inttest/html/__snapshots__/AllViewControllerTest--ALLIANCE_VIEWS-SHOW_MANAGEMENT.html +++ b/tests/inttest/html/__snapshots__/AllViewControllerTest--ALLIANCE_VIEWS-SHOW_MANAGEMENT.html @@ -45,7 +45,7 @@
- 12 / 10 + 13 / 10
diff --git a/tests/inttest/html/__snapshots__/AllViewControllerTest--COLONY_VIEWS-SHOW_SOCIAL.html b/tests/inttest/html/__snapshots__/AllViewControllerTest--COLONY_VIEWS-SHOW_SOCIAL.html index c1119b441..7d563887c 100644 --- a/tests/inttest/html/__snapshots__/AllViewControllerTest--COLONY_VIEWS-SHOW_SOCIAL.html +++ b/tests/inttest/html/__snapshots__/AllViewControllerTest--COLONY_VIEWS-SHOW_SOCIAL.html @@ -71,7 +71,7 @@ - 12 + 13 (0) @@ -107,7 +107,7 @@ - 12 + 13 (0) diff --git a/tests/inttest/html/__snapshots__/AllViewControllerTest--DATABASE_VIEWS-SHOW_TOP_CREW.html b/tests/inttest/html/__snapshots__/AllViewControllerTest--DATABASE_VIEWS-SHOW_TOP_CREW.html index 8507e762d..d8934f4e5 100644 --- a/tests/inttest/html/__snapshots__/AllViewControllerTest--DATABASE_VIEWS-SHOW_TOP_CREW.html +++ b/tests/inttest/html/__snapshots__/AllViewControllerTest--DATABASE_VIEWS-SHOW_TOP_CREW.html @@ -34,7 +34,7 @@
- 12 + 13
diff --git a/tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_CREWMAN_DETAILS.html b/tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_CREWMAN_DETAILS.html new file mode 100644 index 000000000..281fea644 --- /dev/null +++ b/tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_CREWMAN_DETAILS.html @@ -0,0 +1,61 @@ + + + + + + + +
+
/ +
+
+
+ +
+
+
+
+
Skills
+
+
+
Commander
+
+ Rekrut (89) +
+
+
+
Captain
+
+ Kadett (178) +
+
+
+
+
+
+
Anzahl
+
+ + + +
+
+
+ + + + + + + + +
EintragDatum
Keine Einträge vorhanden
+
+
+
+ + + + diff --git a/tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_SPACECRAFTDETAILS.html b/tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_SPACECRAFTDETAILS.html index 5b108616a..054fcb7c5 100644 --- a/tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_SPACECRAFTDETAILS.html +++ b/tests/inttest/html/__snapshots__/AllViewControllerTest--SPACECRAFT_VIEWS-SHOW_SPACECRAFTDETAILS.html @@ -89,7 +89,7 @@ -
+
Crewman
@@ -100,8 +100,8 @@
- -
Crewman
+ +
Rekrut
@@ -109,7 +109,7 @@ -
+
Crewman
@@ -120,8 +120,8 @@
- -
Crewman
+ +
Rekrut
@@ -129,7 +129,7 @@ -
+
Crewman
@@ -140,8 +140,8 @@
- -
Crewman
+ +
Rekrut
@@ -149,7 +149,7 @@ -
+
Crewman
@@ -160,8 +160,8 @@
- -
Crewman
+ +
Rekrut
@@ -169,7 +169,7 @@ -
+
Crewman
@@ -180,8 +180,8 @@
- -
Crewman
+ +
Rekrut
@@ -189,7 +189,7 @@ -
+
Crewman
@@ -200,8 +200,8 @@
- -
Crewman
+ +
Rekrut
@@ -209,7 +209,7 @@ -
+
Crewman
@@ -220,8 +220,8 @@
- -
Crewman
+ +
Rekrut
@@ -229,7 +229,7 @@ -
+
Crewman
@@ -240,8 +240,8 @@
- -
Crewman
+ +
Rekrut
@@ -249,7 +249,7 @@ -
+
Crewman
@@ -260,8 +260,8 @@
- -
Crewman
+ +
Rekrut
@@ -269,7 +269,7 @@ -
+
Crewman
@@ -280,8 +280,8 @@
- -
Crewman
+ +
Rekrut
@@ -289,7 +289,7 @@ -
+
Crewman
@@ -300,8 +300,8 @@
- -
Crewman
+ +
Rekrut
diff --git a/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--COMMUNICATION_VIEWS-DEFAULT_VIEW.html b/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--COMMUNICATION_VIEWS-DEFAULT_VIEW.html index 2e9ae1510..c0f049960 100644 --- a/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--COMMUNICATION_VIEWS-DEFAULT_VIEW.html +++ b/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--COMMUNICATION_VIEWS-DEFAULT_VIEW.html @@ -116,7 +116,7 @@
- 12 / 10 + 13 / 10
diff --git a/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--MAINDESK_VIEWS-DEFAULT_VIEW.html b/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--MAINDESK_VIEWS-DEFAULT_VIEW.html index 2e9ae1510..c0f049960 100644 --- a/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--MAINDESK_VIEWS-DEFAULT_VIEW.html +++ b/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--MAINDESK_VIEWS-DEFAULT_VIEW.html @@ -116,7 +116,7 @@
- 12 / 10 + 13 / 10
diff --git a/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--STATION_VIEWS-DEFAULT_VIEW.html b/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--STATION_VIEWS-DEFAULT_VIEW.html index ff7e39c38..53b97ffcc 100644 --- a/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--STATION_VIEWS-DEFAULT_VIEW.html +++ b/tests/inttest/html/__snapshots__/DefaultViewsControllerTest--STATION_VIEWS-DEFAULT_VIEW.html @@ -93,7 +93,7 @@ - 1 + 2 diff --git a/tests/unit/Component/Crew/Skill/CreateEnhancementLogTest.php b/tests/unit/Component/Crew/Skill/CreateEnhancementLogTest.php new file mode 100644 index 000000000..7167eab68 --- /dev/null +++ b/tests/unit/Component/Crew/Skill/CreateEnhancementLogTest.php @@ -0,0 +1,224 @@ +skillEnhancementLogRepository = $this->mock(SkillEnhancementLogRepositoryInterface::class); + $this->stuTime = $this->mock(StuTime::class); + + $this->subject = new CreateEnhancementLog( + $this->skillEnhancementLogRepository, + $this->stuTime + ); + } + + public function testCreateEnhancementLogWithoutPromotion(): void + { + $enhancement = $this->mock(SkillEnhancementInterface::class); + $crew = $this->mock(CrewInterface::class); + $crewSkill = $this->mock(CrewSkillInterface::class); + $log = $this->mock(SkillEnhancementLogInterface::class); + $user = $this->mock(UserInterface::class); + + $crew->shouldReceive('getId') + ->withNoArgs() + ->once() + ->andReturn(123); + $crew->shouldReceive('getName') + ->withNoArgs() + ->once() + ->andReturn('CREW'); + $crew->shouldReceive('getUser') + ->withNoArgs() + ->once() + ->andReturn($user); + + $crewSkill->shouldReceive('getExpertise') + ->withNoArgs() + ->once() + ->andReturn(42); + $crewSkill->shouldReceive('getCrew') + ->withNoArgs() + ->once() + ->andReturn($crew); + $crewSkill->shouldReceive('getRank') + ->withNoArgs() + ->once() + ->andReturn(CrewSkillLevelEnum::CADET); + + $this->stuTime->shouldReceive('time') + ->withNoArgs() + ->once() + ->andReturn(123123); + + $log->shouldReceive('setUser') + ->with($user) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setEnhancement') + ->with($enhancement) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setCrewName') + ->with('CREW') + ->once() + ->andReturnSelf(); + $log->shouldReceive('setShipName') + ->with('SHIP') + ->once() + ->andReturnSelf(); + $log->shouldReceive('setCrewId') + ->with(123) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setExpertise') + ->with(5) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setExpertiseSum') + ->with(42) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setPromotion') + ->with(null) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setTimestamp') + ->with(123123) + ->once() + ->andReturnSelf(); + + $this->skillEnhancementLogRepository->shouldReceive('prototype') + ->withNoArgs() + ->once() + ->andReturn($log); + $this->skillEnhancementLogRepository->shouldReceive('save') + ->with($log) + ->once(); + + $this->subject->createEnhancementLog( + $crewSkill, + 'SHIP', + $enhancement, + 5, + CrewSkillLevelEnum::CADET + ); + } + + public function testCreateEnhancementLogWithPromotion(): void + { + $enhancement = $this->mock(SkillEnhancementInterface::class); + $crew = $this->mock(CrewInterface::class); + $crewSkill = $this->mock(CrewSkillInterface::class); + $log = $this->mock(SkillEnhancementLogInterface::class); + $user = $this->mock(UserInterface::class); + + $crew->shouldReceive('getId') + ->withNoArgs() + ->once() + ->andReturn(123); + $crew->shouldReceive('getName') + ->withNoArgs() + ->once() + ->andReturn('CREW'); + $crew->shouldReceive('getUser') + ->withNoArgs() + ->once() + ->andReturn($user); + + $crewSkill->shouldReceive('getExpertise') + ->withNoArgs() + ->once() + ->andReturn(42); + $crewSkill->shouldReceive('getCrew') + ->withNoArgs() + ->once() + ->andReturn($crew); + $crewSkill->shouldReceive('getRank') + ->withNoArgs() + ->once() + ->andReturn(CrewSkillLevelEnum::ENSIGN); + + $this->stuTime->shouldReceive('time') + ->withNoArgs() + ->once() + ->andReturn(123123); + + $log->shouldReceive('setUser') + ->with($user) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setEnhancement') + ->with($enhancement) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setCrewName') + ->with('CREW') + ->once() + ->andReturnSelf(); + $log->shouldReceive('setShipName') + ->with('SHIP') + ->once() + ->andReturnSelf(); + $log->shouldReceive('setCrewId') + ->with(123) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setExpertise') + ->with(5) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setExpertiseSum') + ->with(42) + ->once() + ->andReturnSelf(); + $log->shouldReceive('setPromotion') + ->with('Beförderung Kadett -> Fähnrich') + ->once() + ->andReturnSelf(); + $log->shouldReceive('setTimestamp') + ->with(123123) + ->once() + ->andReturnSelf(); + + $this->skillEnhancementLogRepository->shouldReceive('prototype') + ->withNoArgs() + ->once() + ->andReturn($log); + $this->skillEnhancementLogRepository->shouldReceive('save') + ->with($log) + ->once(); + + $this->subject->createEnhancementLog( + $crewSkill, + 'SHIP', + $enhancement, + 5, + CrewSkillLevelEnum::CADET + ); + } +} diff --git a/tests/unit/Component/Crew/Skill/CrewEnhancementTest.php b/tests/unit/Component/Crew/Skill/CrewEnhancementTest.php new file mode 100644 index 000000000..12de695fd --- /dev/null +++ b/tests/unit/Component/Crew/Skill/CrewEnhancementTest.php @@ -0,0 +1,123 @@ +skillEnhancementCache = $this->mock(SkillEnhancementCacheInterface::class); + $this->raiseExpertise = $this->mock(RaiseExpertise::class); + + $this->target = $this->mock(SpacecraftInterface::class); + + $this->subject = new CrewEnhancement( + $this->skillEnhancementCache, + $this->raiseExpertise + ); + } + + public function testAddExpertiseExpectNothingIfEnhancementsEmpty(): void + { + $this->skillEnhancementCache->shouldReceive('getSkillEnhancements') + ->with(SkillEnhancementEnum::FINISH_ASTRO_MAPPING) + ->once() + ->andReturn(null); + + $this->subject->addExpertise($this->target, SkillEnhancementEnum::FINISH_ASTRO_MAPPING, 100); + } + + public function testAddExpertiseExpectRaisingAndLogs(): void + { + $enhancement = $this->mock(SkillEnhancementInterface::class); + $crewAssignmentWithoutPosition = $this->mock(CrewAssignmentInterface::class); + $crewAssignmentCaptain = $this->mock(CrewAssignmentInterface::class); + $crewAssignmentNewbieTechnician = $this->mock(CrewAssignmentInterface::class); + $crewAssignmentSkilledTechnician = $this->mock(CrewAssignmentInterface::class); + $crewNewbieTechnician = $this->mock(CrewInterface::class); + $crewSkilledTechnician = $this->mock(CrewInterface::class); + + $this->skillEnhancementCache->shouldReceive('getSkillEnhancements') + ->with(SkillEnhancementEnum::FINISH_ASTRO_MAPPING) + ->once() + ->andReturn([CrewPositionEnum::TECHNICAL->value => $enhancement]); + + $this->target->shouldReceive('getCrewAssignments') + ->withNoArgs() + ->once() + ->andReturn(new ArrayCollection([ + $crewAssignmentWithoutPosition, + $crewAssignmentCaptain, + $crewAssignmentNewbieTechnician, + $crewAssignmentSkilledTechnician + ])); + + $crewAssignmentWithoutPosition->shouldReceive('getPosition') + ->withNoArgs() + ->once() + ->andReturn(null); + $crewAssignmentCaptain->shouldReceive('getPosition') + ->withNoArgs() + ->once() + ->andReturn(CrewPositionEnum::CAPTAIN); + $crewAssignmentNewbieTechnician->shouldReceive('getPosition') + ->withNoArgs() + ->once() + ->andReturn(CrewPositionEnum::TECHNICAL); + $crewAssignmentSkilledTechnician->shouldReceive('getPosition') + ->withNoArgs() + ->once() + ->andReturn(CrewPositionEnum::TECHNICAL); + + $crewAssignmentNewbieTechnician->shouldReceive('getCrew') + ->withNoArgs() + ->once() + ->andReturn($crewNewbieTechnician); + $crewAssignmentSkilledTechnician->shouldReceive('getCrew') + ->withNoArgs() + ->once() + ->andReturn($crewSkilledTechnician); + + $this->raiseExpertise->shouldReceive('raiseExpertise') + ->with( + $crewNewbieTechnician, + $this->target, + CrewPositionEnum::TECHNICAL, + $enhancement, + 10 + ); + $this->raiseExpertise->shouldReceive('raiseExpertise') + ->with( + $crewSkilledTechnician, + $this->target, + CrewPositionEnum::TECHNICAL, + $enhancement, + 10 + ); + + $this->subject->addExpertise($this->target, SkillEnhancementEnum::FINISH_ASTRO_MAPPING, 10); + } +} diff --git a/tests/unit/Component/Crew/Skill/CrewSkillLevelEnumTest.php b/tests/unit/Component/Crew/Skill/CrewSkillLevelEnumTest.php new file mode 100644 index 000000000..e1d94fd01 --- /dev/null +++ b/tests/unit/Component/Crew/Skill/CrewSkillLevelEnumTest.php @@ -0,0 +1,47 @@ +assertEquals($expectedSkillLevel, $result); + } +} diff --git a/tests/unit/Component/Crew/Skill/RaiseExpertiseTest.php b/tests/unit/Component/Crew/Skill/RaiseExpertiseTest.php new file mode 100644 index 000000000..87c979f3b --- /dev/null +++ b/tests/unit/Component/Crew/Skill/RaiseExpertiseTest.php @@ -0,0 +1,179 @@ +crewSkillRepository = $this->mock(CrewSkillRepositoryInterface::class); + $this->crewRepository = $this->mock(CrewRepositoryInterface::class); + $this->createEnhancementLog = $this->mock(CreateEnhancementLog::class); + + $this->subject = new RaiseExpertise( + $this->crewSkillRepository, + $this->crewRepository, + $this->createEnhancementLog + ); + } + + public function testRaiseExpertiseExpectSkillCreationWhenUnskilled(): void + { + $spacecraft = $this->mock(SpacecraftInterface::class); + $enhancement = $this->mock(SkillEnhancementInterface::class); + $crewNewbieTechnician = $this->mock(CrewInterface::class); + $newSkill = $this->mock(CrewSkillInterface::class); + + $skillsNewbieTechnician = new ArrayCollection(); + + $spacecraft->shouldReceive('getName') + ->withNoArgs() + ->andReturn('SHIP'); + + $crewNewbieTechnician->shouldReceive('getSkills') + ->withNoArgs() + ->once() + ->andReturn($skillsNewbieTechnician); + + $enhancement->shouldReceive('getExpertise') + ->withNoArgs() + ->andReturn(42); + + $newSkill->shouldReceive('setCrew') + ->with($crewNewbieTechnician) + ->once() + ->andReturnSelf(); + $newSkill->shouldReceive('setPosition') + ->with(CrewPositionEnum::TECHNICAL) + ->once() + ->andReturnSelf(); + $newSkill->shouldReceive('getRank') + ->withNoArgs() + ->andReturn(CrewSkillLevelEnum::RECRUIT); + + $newSkill->shouldReceive('increaseExpertise') + ->with(5) + ->once(); + $newSkill->shouldReceive('getExpertise') + ->withNoArgs() + ->andReturn(5); + + $this->crewSkillRepository->shouldReceive('prototype') + ->withNoArgs() + ->once() + ->andReturn($newSkill); + $this->crewSkillRepository->shouldReceive('save') + ->with($newSkill) + ->once(); + + $this->createEnhancementLog->shouldReceive('createEnhancementLog') + ->with( + $newSkill, + 'SHIP', + $enhancement, + 5, + CrewSkillLevelEnum::RECRUIT + ) + ->once(); + + $this->subject->raiseExpertise( + $crewNewbieTechnician, + $spacecraft, + CrewPositionEnum::TECHNICAL, + $enhancement, + 10 + ); + + $this->assertEquals([CrewPositionEnum::TECHNICAL->value => $newSkill], $skillsNewbieTechnician->toArray()); + } + + public function testRaiseExpertiseExpectSkillEnhancementWhenSkilled(): void + { + $spacecraft = $this->mock(SpacecraftInterface::class); + $enhancement = $this->mock(SkillEnhancementInterface::class); + $crewSkilledTechnician = $this->mock(CrewInterface::class); + $existingSkill = $this->mock(CrewSkillInterface::class); + + $skillsSkilledTechnician = new ArrayCollection([CrewPositionEnum::TECHNICAL->value => $existingSkill]); + + $spacecraft->shouldReceive('getName') + ->withNoArgs() + ->andReturn('SHIP'); + + $crewSkilledTechnician->shouldReceive('getSkills') + ->withNoArgs() + ->once() + ->andReturn($skillsSkilledTechnician); + $crewSkilledTechnician->shouldReceive('setRank') + ->with(CrewSkillLevelEnum::CADET) + ->once(); + + $enhancement->shouldReceive('getExpertise') + ->withNoArgs() + ->andReturn(50); + + $existingSkill->shouldReceive('increaseExpertise') + ->with(50) + ->once(); + $existingSkill->shouldReceive('getExpertise') + ->withNoArgs() + ->andReturn(77); + $existingSkill->shouldReceive('getRank') + ->withNoArgs() + ->andReturn(CrewSkillLevelEnum::RECRUIT, CrewSkillLevelEnum::CADET, CrewSkillLevelEnum::CADET); + + $this->crewSkillRepository->shouldReceive('save') + ->with($existingSkill) + ->once(); + + $this->crewRepository->shouldReceive('save') + ->with($crewSkilledTechnician) + ->once(); + + $this->createEnhancementLog->shouldReceive('createEnhancementLog') + ->with( + $existingSkill, + 'SHIP', + $enhancement, + 50, + CrewSkillLevelEnum::RECRUIT + ) + ->once(); + + $this->subject->raiseExpertise( + $crewSkilledTechnician, + $spacecraft, + CrewPositionEnum::TECHNICAL, + $enhancement, + 100 + ); + $this->assertEquals([CrewPositionEnum::TECHNICAL->value => $existingSkill], $skillsSkilledTechnician->toArray()); + } +} diff --git a/tests/unit/Component/Crew/Skill/SkillEnhancementCacheTest.php b/tests/unit/Component/Crew/Skill/SkillEnhancementCacheTest.php new file mode 100644 index 000000000..f5337ea80 --- /dev/null +++ b/tests/unit/Component/Crew/Skill/SkillEnhancementCacheTest.php @@ -0,0 +1,78 @@ +skillEnhancementRepository = $this->mock(SkillEnhancementRepositoryInterface::class); + + $this->subject = new SkillEnhancementCache( + $this->skillEnhancementRepository + ); + } + + public function testGetSkillEnhancements(): void + { + $captainEnhancementForDestruction = $this->mock(SkillEnhancementInterface::class); + $commanderEnhancementForDestruction = $this->mock(SkillEnhancementInterface::class); + + $captainEnhancementForDestruction->shouldReceive('getType') + ->withNoArgs() + ->once() + ->andReturn(SkillEnhancementEnum::SPACECRAFT_DESTRUCTION); + $commanderEnhancementForDestruction->shouldReceive('getType') + ->withNoArgs() + ->once() + ->andReturn(SkillEnhancementEnum::SPACECRAFT_DESTRUCTION); + + $captainEnhancementForDestruction->shouldReceive('getPosition') + ->withNoArgs() + ->once() + ->andReturn(CrewPositionEnum::CAPTAIN); + $commanderEnhancementForDestruction->shouldReceive('getPosition') + ->withNoArgs() + ->once() + ->andReturn(CrewPositionEnum::COMMAND); + + $this->skillEnhancementRepository->shouldReceive('findAll') + ->withNoArgs() + ->once() + ->andReturn([ + $captainEnhancementForDestruction, + $commanderEnhancementForDestruction + ]); + + $resultAstro = $this->subject->getSkillEnhancements(SkillEnhancementEnum::FINISH_ASTRO_MAPPING); + $resultDestruction = $this->subject->getSkillEnhancements(SkillEnhancementEnum::SPACECRAFT_DESTRUCTION); + + $this->assertNull($resultAstro); + $this->assertEquals([ + CrewPositionEnum::CAPTAIN->value => $captainEnhancementForDestruction, + CrewPositionEnum::COMMAND->value => $commanderEnhancementForDestruction + ], $resultDestruction); + } +} diff --git a/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderColonyTest.php b/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderColonyTest.php index 9772150af..ae7df1520 100644 --- a/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderColonyTest.php +++ b/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderColonyTest.php @@ -112,11 +112,11 @@ public function testGetFreeCrewAmount(): void $this->assertEquals(123, $this->subject->getFreeCrewAmount()); } - public function testCreateCrewAssignment(): void + public function testCreateCrewAssignments(): void { $ship = $this->mock(ShipInterface::class); - $this->crewCreator->shouldReceive('createCrewAssignment') + $this->crewCreator->shouldReceive('createCrewAssignments') ->with($ship, $this->colony, 42) ->once() ->andReturn(123); diff --git a/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderStationTest.php b/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderStationTest.php index e6a0f68ec..88b2e20d7 100644 --- a/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderStationTest.php +++ b/tests/unit/Lib/SpacecraftManagement/Provider/ManagerProviderStationTest.php @@ -159,11 +159,11 @@ public function testGetFreeCrewAmount(): void $this->assertEquals(123, $this->subject->getFreeCrewAmount()); } - public function testCreateCrewAssignment(): void + public function testCreateCrewAssignments(): void { $ship = $this->mock(ShipInterface::class); - $this->crewCreator->shouldReceive('createCrewAssignment') + $this->crewCreator->shouldReceive('createCrewAssignments') ->with($ship, $this->station, 42) ->once() ->andReturn(123); diff --git a/tests/unit/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtilTest.php b/tests/unit/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtilTest.php index 40c2391c1..b8d30ae52 100644 --- a/tests/unit/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtilTest.php +++ b/tests/unit/Module/Spacecraft/Lib/CloseCombat/CloseCombatUtilTest.php @@ -7,8 +7,7 @@ use Doctrine\Common\Collections\ArrayCollection; use Mockery\MockInterface; use Override; -use Stu\Component\Crew\CrewEnum; -use Stu\Orm\Entity\CrewInterface; +use Stu\Component\Crew\CrewPositionEnum; use Stu\Orm\Entity\FactionInterface; use Stu\Orm\Entity\CrewAssignmentInterface; use Stu\Orm\Entity\ShipInterface; @@ -68,12 +67,6 @@ public function testGetCombatGroupExpectRightOrder(): void $shipCrew4 = $this->mock(CrewAssignmentInterface::class); $shipCrew5 = $this->mock(CrewAssignmentInterface::class); $shipCrew6 = $this->mock(CrewAssignmentInterface::class); - $crew1 = $this->mock(CrewInterface::class); - $crew2 = $this->mock(CrewInterface::class); - $crew3 = $this->mock(CrewInterface::class); - $crew4 = $this->mock(CrewInterface::class); - $crew5 = $this->mock(CrewInterface::class); - $crew6 = $this->mock(CrewInterface::class); $crewList = new ArrayCollection([ $shipCrew4, @@ -84,43 +77,24 @@ public function testGetCombatGroupExpectRightOrder(): void $shipCrew6 ]); - $shipCrew1->shouldReceive('getCrew') + $shipCrew1->shouldReceive('getFightCapability') ->withNoArgs() - ->andReturn($crew1); - $shipCrew2->shouldReceive('getCrew') + ->andReturn(CrewPositionEnum::NAVIGATION->getFightCapability()); + $shipCrew2->shouldReceive('getFightCapability') ->withNoArgs() - ->andReturn($crew2); - $shipCrew3->shouldReceive('getCrew') + ->andReturn(CrewPositionEnum::SECURITY->getFightCapability()); + $shipCrew3->shouldReceive('getFightCapability') ->withNoArgs() - ->andReturn($crew3); - $shipCrew4->shouldReceive('getCrew') + ->andReturn(CrewPositionEnum::CAPTAIN->getFightCapability()); + $shipCrew4->shouldReceive('getFightCapability') ->withNoArgs() - ->andReturn($crew4); - $shipCrew5->shouldReceive('getCrew') + ->andReturn(CrewPositionEnum::SCIENCE->getFightCapability()); + $shipCrew5->shouldReceive('getFightCapability') ->withNoArgs() - ->andReturn($crew5); - $shipCrew6->shouldReceive('getCrew') + ->andReturn(CrewPositionEnum::SCIENCE->getFightCapability()); + $shipCrew6->shouldReceive('getFightCapability') ->withNoArgs() - ->andReturn($crew6); - - $crew1->shouldReceive('getType') - ->withNoArgs() - ->andReturn(CrewEnum::CREW_TYPE_NAVIGATION); - $crew2->shouldReceive('getType') - ->withNoArgs() - ->andReturn(CrewEnum::CREW_TYPE_SECURITY); - $crew3->shouldReceive('getType') - ->withNoArgs() - ->andReturn(CrewEnum::CREW_TYPE_CAPTAIN); - $crew4->shouldReceive('getType') - ->withNoArgs() - ->andReturn(CrewEnum::CREW_TYPE_SCIENCE); - $crew5->shouldReceive('getType') - ->withNoArgs() - ->andReturn(CrewEnum::CREW_TYPE_SCIENCE); - $crew6->shouldReceive('getType') - ->withNoArgs() - ->andReturn(CrewEnum::CREW_TYPE_SCIENCE); + ->andReturn(CrewPositionEnum::SCIENCE->getFightCapability()); $this->ship->shouldReceive('getCrewAssignments') ->withNoArgs() @@ -139,24 +113,14 @@ public function testGetCombatValue(): void { $shipCrew1 = $this->mock(CrewAssignmentInterface::class); $shipCrew2 = $this->mock(CrewAssignmentInterface::class); - $crew1 = $this->mock(CrewInterface::class); - $crew2 = $this->mock(CrewInterface::class); $faction = $this->mock(FactionInterface::class); - $shipCrew1->shouldReceive('getCrew') - ->withNoArgs() - ->andReturn($crew1); - $shipCrew2->shouldReceive('getCrew') + $shipCrew1->shouldReceive('getFightCapability') ->withNoArgs() - ->andReturn($crew2); - $crew1->shouldReceive('getType') + ->andReturn(CrewPositionEnum::CAPTAIN->getFightCapability()); + $shipCrew2->shouldReceive('getFightCapability') ->withNoArgs() - ->once() - ->andReturn(CrewEnum::CREW_TYPE_CAPTAIN); - $crew2->shouldReceive('getType') - ->withNoArgs() - ->once() - ->andReturn(CrewEnum::CREW_TYPE_NAVIGATION); + ->andReturn(CrewPositionEnum::NAVIGATION->getFightCapability()); $faction->shouldReceive('getCloseCombatScore') ->withNoArgs() diff --git a/tests/unit/Module/Spacecraft/Lib/Crew/TroopTransferUtilityTest.php b/tests/unit/Module/Spacecraft/Lib/Crew/TroopTransferUtilityTest.php index 8c6302e8e..36496f795 100644 --- a/tests/unit/Module/Spacecraft/Lib/Crew/TroopTransferUtilityTest.php +++ b/tests/unit/Module/Spacecraft/Lib/Crew/TroopTransferUtilityTest.php @@ -208,7 +208,7 @@ public function testAssignCrewWhenShipTarget(): void ->with($target) ->once() ->andReturnSelf(); - $shipCrew->shouldReceive('setSlot') + $shipCrew->shouldReceive('setPosition') ->with(null) ->once(); @@ -247,7 +247,7 @@ public function testAssignCrewWhenColonyTarget(): void ->with($target) ->once() ->andReturnSelf(); - $shipCrew->shouldReceive('setSlot') + $shipCrew->shouldReceive('setPosition') ->with(null) ->once(); diff --git a/tests/unit/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequenceTest.php b/tests/unit/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequenceTest.php index f1f6c52af..d9972761c 100644 --- a/tests/unit/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequenceTest.php +++ b/tests/unit/Module/Spacecraft/Lib/Movement/Component/Consequence/PostFlight/PostFlightAstroMappingConsequenceTest.php @@ -7,6 +7,8 @@ use Mockery; use Mockery\MockInterface; use Override; +use Stu\Component\Crew\Skill\CrewEnhancementInterface; +use Stu\Component\Crew\Skill\SkillEnhancementEnum; use Stu\Component\Ship\AstronomicalMappingEnum; use Stu\Component\Spacecraft\SpacecraftStateEnum; use Stu\Component\Spacecraft\System\Data\AstroLaboratorySystemData; @@ -24,12 +26,14 @@ use Stu\Orm\Entity\StarSystemInterface; use Stu\Orm\Entity\UserInterface; use Stu\Orm\Repository\AstroEntryRepositoryInterface; +use Stu\StuMocks; use Stu\StuTestCase; class PostFlightAstroMappingConsequenceTest extends StuTestCase { private MockInterface&AstroEntryRepositoryInterface $astroEntryRepository; private MockInterface&AstroEntryLibInterface $astroEntryLib; + private MockInterface&CrewEnhancementInterface $crewEnhancement; private MockInterface&CreatePrestigeLogInterface $createPrestigeLog; private MockInterface&MessageFactoryInterface $messageFactory; @@ -46,6 +50,7 @@ protected function setUp(): void { $this->astroEntryRepository = $this->mock(AstroEntryRepositoryInterface::class); $this->astroEntryLib = $this->mock(AstroEntryLibInterface::class); + $this->crewEnhancement = $this->mock(CrewEnhancementInterface::class); $this->createPrestigeLog = $this->mock(CreatePrestigeLogInterface::class); $this->messageFactory = $this->mock(MessageFactoryInterface::class); @@ -53,6 +58,8 @@ protected function setUp(): void $this->wrapper = $this->mock(ShipWrapperInterface::class); $this->flightRoute = $this->mock(FlightRouteInterface::class); + StuMocks::get()->mockService(CrewEnhancementInterface::class, $this->crewEnhancement); + $this->wrapper->shouldReceive('get') ->zeroOrMoreTimes() ->andReturn($this->ship); @@ -65,6 +72,12 @@ protected function setUp(): void ); } + #[Override] + protected function tearDown(): void + { + StuMocks::get()->reset(); + } + public function testTriggerExpectNothingWhenShipDestroyed(): void { $messages = $this->mock(MessageCollectionInterface::class); @@ -132,7 +145,6 @@ public function testTriggerExpectNothingWhenNeitherInSystemNorInRegion(): void public function testTriggerExpectNothingWhenNoAstroEntryPresent(): void { - $messages = $this->mock(MessageCollectionInterface::class); $this->ship->shouldReceive('getCondition->isDestroyed') @@ -245,6 +257,10 @@ public function testTriggerExpectArrivingWaypoint(): void ) ->once(); + $this->crewEnhancement->shouldReceive('addExpertise') + ->with($this->ship, SkillEnhancementEnum::REACH_ASTRO_WAYPOINT, 100) + ->once(); + $messages->shouldReceive('add') ->with($message) ->once(); @@ -268,7 +284,6 @@ public function testTriggerExpectArrivingWaypoint(): void public function testTriggerExpectMeasured(): void { - $map = $this->mock(MapInterface::class); $user = $this->mock(UserInterface::class); $messages = $this->mock(MessageCollectionInterface::class); @@ -354,6 +369,9 @@ public function testTriggerExpectMeasured(): void ) ->once(); + $this->crewEnhancement->shouldReceive('addExpertise') + ->with($this->ship, SkillEnhancementEnum::REACH_ASTRO_WAYPOINT, 100) + ->once(); $messages->shouldReceive('add') ->with($message)