diff options
author | Daniel Weipert <git@mail.dweipert.de> | 2024-01-11 13:15:02 +0100 |
---|---|---|
committer | Daniel Weipert <git@mail.dweipert.de> | 2024-01-11 13:15:02 +0100 |
commit | 09caff2b2a06d1f8ac8203567035a21c612165f9 (patch) | |
tree | 999be04ff0a418a33e438be9befc8c9297e383f4 /src | |
parent | 6301f63bd348109b8693a922f02e16d49205a8fd (diff) |
send resources
Diffstat (limited to 'src')
25 files changed, 424 insertions, 262 deletions
diff --git a/src/EventRunner.php b/src/EventRunner.php index 2f2fd8b..e4bdb40 100644 --- a/src/EventRunner.php +++ b/src/EventRunner.php @@ -9,6 +9,8 @@ use App\Model\Building\IronMine; use App\Model\Building\ResourceGenerator; use App\Model\Building\Storage; use App\Model\Building\WoodCutter; +use App\Model\Event\SendResources; +use App\Model\Event\SendResourcesCarriers; use App\Model\Event\SendUnits; use App\Model\Event\TrainUnits; use App\Model\Event\UpgradeBuilding; @@ -71,6 +73,40 @@ class EventRunner $event->dbDelete(); } + # Send Resources + + $results = DB::query(<<<SQL + select * from events + inner join events_send_resources as event + on events.id = event.event_id + where events.time < now() + SQL)->fetchAll(); + + foreach ($results as $row) { + /**@var SendResources $event*/ + $event = DB::convertToModel(SendResources::class, $row); + $event(); + + $event->dbDelete(); + } + + # Send Resources Carriers + + $results = DB::query(<<<SQL + select * from events + inner join events_send_resources_carriers as event + on events.id = event.event_id + where events.time < now() + SQL)->fetchAll(); + + foreach ($results as $row) { + /**@var SendResourcesCarriers $event*/ + $event = DB::convertToModel(SendResourcesCarriers::class, $row); + $event(); + + $event->dbDelete(); + } + // Resources diff --git a/src/Model/Building.php b/src/Model/Building.php index e42af03..36bdc68 100644 --- a/src/Model/Building.php +++ b/src/Model/Building.php @@ -4,6 +4,7 @@ namespace App\Model; use App\DB; use App\Model; +use App\Support\ResourceType; class Building { @@ -17,11 +18,15 @@ class Building public \DateTime $updatedAt; public string $unitType; + public int $buildTimeFactor; + public array $resourceRequirementsBase; public array $resourceRequirementsFactor; + public array $buildingRequirements; public array $techRequirements; + public int $maxLevel; @@ -80,6 +85,7 @@ class Building return $this->level + count($upgradeEvents); } + public function getBuildTime(): int { return $this->getBuildTimeForLevel($this->level + 1); @@ -92,6 +98,7 @@ class Building return intval($level * ($level / $townHall->level) * $_ENV['BASE_BUILDING_BUILD_TIME_FACTOR'] * $this->buildTimeFactor); } + /** * @return array<string, int> */ @@ -106,7 +113,7 @@ class Building public function getResourceRequirementsForLevel(int $level): array { $resourceRequirements = []; - foreach (['wood', 'clay', 'iron'] as $resourceType) { + foreach (ResourceType::asPropertiesForBuildings() as $resourceType) { $base = $this->resourceRequirementsBase[$resourceType]; $factor = $this->resourceRequirementsFactor[$resourceType]; diff --git a/src/Model/Building/Embassy.php b/src/Model/Building/Embassy.php index a8a1ec4..4238c90 100644 --- a/src/Model/Building/Embassy.php +++ b/src/Model/Building/Embassy.php @@ -6,7 +6,7 @@ use App\Model\Building; class Embassy extends Building { - public int $buildTimeFactor = 1; + public int $buildTimeFactor = 10; public int $maxLevel = 25; public array $resourceRequirementsBase = [ diff --git a/src/Model/Building/Marketplace.php b/src/Model/Building/PostOffice.php index 8978003..5765a0f 100644 --- a/src/Model/Building/Marketplace.php +++ b/src/Model/Building/PostOffice.php @@ -3,13 +3,13 @@ namespace App\Model\Building; use App\Model\Building; -use App\Model\Unit\Merchant; +use App\Model\Unit\MailCarrier; use App\Model\Village; -class Marketplace extends Building +class PostOffice extends Building { - public string $unitType = 'Merchant'; - public int $buildTimeFactor = 1; + public string $unitType = 'MailCarrier'; + public int $buildTimeFactor = 5; public int $maxLevel = 25; public array $resourceRequirementsBase = [ @@ -25,8 +25,8 @@ class Marketplace extends Building public static function getResourceCapabilities(Village $village): int { - $merchants = Village::getUnit($village, 'Merchant', Village::FETCH_UNIT_RESIDENCE, Village::RETURN_UNIT_EXISTING); + $mailCarriers = Village::getUnit($village, 'MailCarrier', Village::FETCH_UNIT_RESIDENCE, Village::RETURN_UNIT_EXISTING); - return Merchant::getResourceCapabilities($village) * $merchants->amount; + return MailCarrier::getResourceCapabilities($village) * $mailCarriers->amount; } } diff --git a/src/Model/Building/TownHall.php b/src/Model/Building/TownHall.php index 33fd105..84a78a4 100644 --- a/src/Model/Building/TownHall.php +++ b/src/Model/Building/TownHall.php @@ -6,7 +6,7 @@ use App\Model\Building; class TownHall extends Building { - public int $buildTimeFactor = 1; + public int $buildTimeFactor = 2; public int $maxLevel = 25; public array $resourceRequirementsBase = [ diff --git a/src/Model/Event/BaseEvent.php b/src/Model/Event/BaseEvent.php index 0c1795b..2e2564b 100644 --- a/src/Model/Event/BaseEvent.php +++ b/src/Model/Event/BaseEvent.php @@ -17,6 +17,7 @@ abstract class BaseEvent abstract function dbInsert(): void; abstract function dbDelete(): void; + abstract function cancel(): void; public function getEvent(): Event { diff --git a/src/Model/Event/SendResources.php b/src/Model/Event/SendResources.php index 5c751fd..ea9361c 100644 --- a/src/Model/Event/SendResources.php +++ b/src/Model/Event/SendResources.php @@ -5,7 +5,7 @@ namespace App\Model\Event; use App\DB; use App\Model\Event; use App\Model\Unit; -use App\Model\Unit\Merchant; +use App\Model\Unit\MailCarrier; use App\Model\Village; class SendResources extends BaseEvent @@ -26,12 +26,38 @@ class SendResources extends BaseEvent public function __invoke(): void { if ($this->isCanceled) { - // TODO: switch destination and source - // TODO: add resources back to "destination" - // TODO: add merchants back to "destination" + // add resources back to "destination" + DB::query( + 'update villages set wood=wood+:wood, clay=clay+:clay, iron=iron+:iron, food=food+:food where id=:id', + [ + 'wood' => $this->wood, + 'clay' => $this->clay, + 'iron' => $this->iron, + 'food' => $this->food, + 'id' => $this->source, + ] + ); + + // add mailCarriers back to "destination" + $meta = DB::query('select amount, unit_id from events_meta_send_resources_carriers where event_id=:eventId', ['eventId' => $this->id])->fetchAll(); + foreach ($meta as $m) { + $unit = DB::query('select * from village_units where id=:unitId', ['unitId' => $m['unit_id']])->fetch(); + + DB::query('update village_units set amount=amount+:amount where id=:unitId', ['amount' => $m['amount'], 'unitId' => $unit['id']]); + DB::query( + 'update village_units set amount=amount-:amount where type=:unitType and home_village_id=:homeVillageId and residence_village_id=:residenceVillageId and is_traveling=true', + [ + 'amount' => $m['amount'], + 'unitType' => $unit['type'], + 'homeVillageId' => $unit['home_village_id'], + 'residenceVillageId' => $unit['residence_village_id'], + ] + ); + } } else { + // add resources to destination // TODO: account for storage capacity DB::query( 'update villages set wood=wood+:wood, clay=clay+:clay, iron=iron+:iron, food=food+:food where id=:id', @@ -44,26 +70,45 @@ class SendResources extends BaseEvent ] ); - $source = Village::get($this->source); - $destination = Village::get($this->destination); + // create SendResourcesCarriers event with mailCarriers back to source + $source = Village::get($this->destination); + $destination = Village::get($this->source); $event = new Event(); $event->time = (new \DateTime())->add( \DateInterval::createFromDateString( - Unit::getTravelTime(new Merchant(), Village::getDistance($source->x, $source->y, $destination->x, $destination->y)) + Unit::getTravelTime(new MailCarrier(), Village::getDistance($source->x, $source->y, $destination->x, $destination->y)) . ' seconds' ) ); $event->villageId = $this->source; - $sendResourcesMerchants = new SendResourcesMerchants(); - $sendResourcesMerchants->dbInsert($this->id); + $sendResourcesMailCarriers = new SendResourcesCarriers(); + $sendResourcesMailCarriers->event = $event; + $sendResourcesMailCarriers->sendResourcesEventId = $this->id; + $sendResourcesMailCarriers->source = $source->id; + $sendResourcesMailCarriers->destination = $destination->id; + $sendResourcesMailCarriers->dbInsert(); + } + } + + public function cancel(): void + { + $this->event = $this->getEvent(); + $cancelTimeDiff = $this->event->createdAt->diff(new \DateTime()); + $cancelTime = (new \DateTime())->add($cancelTimeDiff); - // TODO: add resources to destination - // (TODO: add foreign merchants to destination)? - // TODO: create SendUnits event with merchants back to source - } + $this->isCanceled = true; + + DB::query( + 'update events set time=:time where id=:id', + ['time' => $cancelTime->format('c'), 'id' => $this->event->id] + ); + DB::query( + 'update events_send_resources set is_canceled=:is_canceled where id=:id', + ['is_canceled' => $this->isCanceled, 'id' => $this->id] + ); } public function dbInsert(): void @@ -90,61 +135,70 @@ class SendResources extends BaseEvent ); $sendResourcesEventId = DB::$connection->lastInsertId(); - $resourceCapabilities = Merchant::getResourceCapabilities($this->event->villageId); + $resourceCapabilities = MailCarrier::getResourceCapabilities($this->event->villageId); $resourcesTotal = $this->wood + $this->clay + $this->iron + $this->food; - $necessaryMerchants = ceil($resourcesTotal / $resourceCapabilities); + $necessaryMailCarriers = ceil($resourcesTotal / $resourceCapabilities); - $merchantsAccountedFor = 0; - while ($merchantsAccountedFor < $necessaryMerchants) { - $merchants = DB::fetch( - Merchant::class, + $mailCarriersAccountedFor = 0; + while ($mailCarriersAccountedFor < $necessaryMailCarriers) { + $mailCarriers = DB::fetch( + MailCarrier::class, 'select * from village_units where type=:type and residence_village_id=:villageId and is_traveling=false', - ['type' => 'Merchant', 'villageId' => $this->source] + ['type' => 'MailCarrier', 'villageId' => $this->source] ); - foreach ($merchants as $merchant) { - /**@type Merchant $merchant*/ + foreach ($mailCarriers as $mailCarrier) { + /**@type MailCarrier $mailCarrier*/ - $currentlyNecessaryMerchants = $necessaryMerchants - $merchantsAccountedFor; - $currentlyUseableMerchants = $currentlyNecessaryMerchants - $merchant->amount < 0 ? $currentlyNecessaryMerchants : $merchant->amount; - $merchantsAccountedFor += $currentlyUseableMerchants; + $currentlyNecessaryMailCarriers = $necessaryMailCarriers - $mailCarriersAccountedFor; + $currentlyUseableMailCarriers = $currentlyNecessaryMailCarriers - $mailCarrier->amount < 0 ? $currentlyNecessaryMailCarriers : $mailCarrier->amount; + $mailCarriersAccountedFor += $currentlyUseableMailCarriers; DB::query( <<<SQL - insert into village_units (amount, type, is_traveling, home_village_id, residence_village_id) - VALUES (:amount, :type, true, :home, :residence) + insert into village_units (amount, type, home_village_id, residence_village_id, is_traveling) + VALUES (:amount, :type, :home, :residence, true) on conflict (type, home_village_id, residence_village_id, is_traveling) - do update set is_traveling=true + do update set amount = village_units.amount+:amount SQL, [ - 'amount' => $currentlyUseableMerchants, - 'type' => 'Merchant', - 'home' => $merchant->homeVillageId, - 'residence' => $merchant->residenceVillageId, + 'amount' => $currentlyUseableMailCarriers, + 'type' => 'MailCarrier', + 'home' => $mailCarrier->homeVillageId, + 'residence' => $mailCarrier->residenceVillageId, ] ); - DB::query('update village_units set amount=amount-:amount where id=:unitId', ['amount' => $necessaryMerchants, 'unitId' => $merchant->id]); + DB::query('update village_units set amount=amount-:amount where id=:unitId', ['amount' => $necessaryMailCarriers, 'unitId' => $mailCarrier->id]); DB::query( <<<SQL - insert into events_send_resources_merchants (event_id, unit_id, amount) + insert into events_meta_send_resources_carriers (event_id, unit_id, amount) VALUES (:event_id, :unit_id, :amount) SQL, [ 'event_id' => $sendResourcesEventId, - 'unit_id' => $merchant->id, - 'amount' => $necessaryMerchants, + 'unit_id' => $mailCarrier->id, + 'amount' => $necessaryMailCarriers, ] ); } } - // TODO: remove resources from source + // remove resources from source + DB::query( + 'update villages set wood=wood-:wood, clay=clay-:clay, iron=iron-:iron, food=food-:food where id=:id', + [ + 'wood' => $this->wood, + 'clay' => $this->clay, + 'iron' => $this->iron, + 'food' => $this->food, + 'id' => $this->source, + ] + ); } public function dbDelete(): void { DB::query('delete from events where id=:id', ['id' => $this->eventId]); DB::query('delete from events_send_resources where id=:id', ['id' => $this->id]); - #DB::query('delete from events_send_resources_merchants where event_id=:id', ['id' => $this->id]); } } diff --git a/src/Model/Event/SendResourcesCarriers.php b/src/Model/Event/SendResourcesCarriers.php new file mode 100644 index 0000000..b6c3772 --- /dev/null +++ b/src/Model/Event/SendResourcesCarriers.php @@ -0,0 +1,70 @@ +<?php + +namespace App\Model\Event; + +use App\DB; + +class SendResourcesCarriers extends BaseEvent +{ + public int $sendResourcesEventId; + + public int $source; + public int $destination; + + /** + * @return void + */ + public function __invoke(): void + { + // add units to destination + $meta = DB::query('select amount, unit_id from events_meta_send_resources_carriers where event_id=:eventId', ['eventId' => $this->id])->fetchAll(); + foreach ($meta as $m) { + $unit = DB::query('select * from village_units where id=:unitId', ['unitId' => $m['unit_id']])->fetch(); + + DB::query('update village_units set amount=amount+:amount where id=:unitId', ['amount' => $m['amount'], 'unitId' => $unit['id']]); + DB::query( + 'update village_units set amount=amount-:amount where type=:unitType and home_village_id=:homeVillageId and residence_village_id=:residenceVillageId and is_traveling=true', + [ + 'amount' => $m['amount'], + 'unitType' => $unit['type'], + 'homeVillageId' => $unit['home_village_id'], + 'residenceVillageId' => $unit['residence_village_id'], + ] + ); + } + } + + public function dbInsert(): void + { + DB::query( + 'insert into events (time, village_id) VALUES (:time, :village_id)', + ['time' => $this->event->time->format('c'), 'village_id' => $this->event->villageId] + ); + $eventId = DB::$connection->lastInsertId(); + + DB::query( + <<<SQL + insert into events_send_resources_carriers (event_id, source, destination) + VALUES (:event_id, :source, :destination) + SQL, + [ + 'event_id' => $eventId, + 'source' => $this->source, + 'destination' => $this->destination, + ] + ); + $sendResourcesCarriersEventId = DB::$connection->lastInsertId(); + + DB::query( + 'update events_meta_send_resources_carriers set event_id=:new_id where event_id=:old_id', + ['old_id' => $this->sendResourcesEventId, 'new_id' => $sendResourcesCarriersEventId] + ); + } + + public function dbDelete(): void + { + DB::query('delete from events where id=:id', ['id' => $this->eventId]); + DB::query('delete from events_send_resources_carriers where id=:id', ['id' => $this->id]); + DB::query('delete from events_meta_send_resources_carriers where event_id=:id', ['id' => $this->id]); + } +} diff --git a/src/Model/Event/SendResourcesMerchants.php b/src/Model/Event/SendResourcesMerchants.php deleted file mode 100644 index a50b2bc..0000000 --- a/src/Model/Event/SendResourcesMerchants.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -namespace App\Model\Event; - -use App\DB; -use App\Model\Event; -use App\Model\Unit; -use App\Model\Unit\Merchant; -use App\Model\Village; - -class SendResourcesMerchants extends BaseEvent -{ - public int $wood = 0; - public int $clay = 0; - public int $iron = 0; - public int $food = 0; - - public int $source; - public int $destination; - - public bool $isCanceled = false; - - /** - * @return void - */ - public function __invoke(): void - { - if ($this->isCanceled) { - // TODO: switch destination and source - // TODO: add resources back to "destination" - // TODO: add merchants back to "destination" - } - - else { - // TODO: account for storage capacity - DB::query( - 'update villages set wood=wood+:wood, clay=clay+:clay, iron=iron+:iron, food=food+:food where id=:id', - [ - 'wood' => $this->wood, - 'clay' => $this->clay, - 'iron' => $this->iron, - 'food' => $this->food, - 'id' => $this->destination, - ] - ); - - // TODO: foreach send_resources_merchants - $source = Village::get($this->source); - $destination = Village::get($this->destination); - $event = new Event(); - $event->time = (new \DateTime())->add( - \DateInterval::createFromDateString( - Unit::getTravelTime(new Merchant(), Village::getDistance($source->x, $source->y, $destination->x, $destination->y)) - . ' seconds' - ) - ); - $event->villageId = $this->source; - $sendUnitsEvent = new SendUnits(); - $sendUnitsEvent->event = $event; - $sendUnitsEvent->type = 'SendBack'; - $sendUnitsEvent->unit = 'Merchant'; - $sendUnitsEvent->amount = $amount; - $sendUnitsEvent->source = $village->id; - $sendUnitsEvent->destination = $destination->id; - $sendUnitsEvent->dbInsert(); - - // TODO: add resources to destination - // (TODO: add foreign merchants to destination)? - // TODO: create SendUnits event with merchants back to source - } - } - - public function dbInsert(int $previouId): void - { - DB::query( - 'update events_send_resources_merchants set event_id=:new_id where event_id=:old_id', - ['old_id' => $previouId, 'new_id' => $this->id] - ); - - /* - DB::query( - 'insert into events (time, village_id) VALUES (:time, :village_id)', - ['time' => $this->event->time->format('c'), 'village_id' => $this->event->villageId] - ); - - DB::query( - <<<SQL - insert into events_send_resources (event_id, wood, clay, iron, food, source, destination, is_canceled) - VALUES (:event_id, :wood, :clay, :iron, :food, :source, :destination, :is_canceled) - SQL, - [ - 'event_id' => DB::$connection->lastInsertId(), - 'wood' => $this->wood, - 'clay' => $this->clay, - 'iron' => $this->iron, - 'food' => $this->food, - 'source' => $this->source, 'destination' => $this->destination, - 'is_canceled' => $this->isCanceled ?: 0, // @see https://www.php.net/manual/de/pdostatement.execute.php#126013 - ] - ); - $sendResourcesEventId = DB::$connection->lastInsertId(); - - $resourceCapabilities = Merchant::getResourceCapabilities($this->event->villageId); - $resourcesTotal = $this->wood + $this->clay + $this->iron + $this->food; - $necessaryMerchants = ceil($resourcesTotal / $resourceCapabilities); - - $merchantsAccountedFor = 0; - while ($merchantsAccountedFor < $necessaryMerchants) { - $merchants = DB::fetch( - Merchant::class, - 'select * from village_units where type=:type and residence_village_id=:villageId and is_traveling=false', - ['type' => 'Merchant', 'villageId' => $this->source] - ); - foreach ($merchants as $merchant) { - $currentlyNecessaryMerchants = $necessaryMerchants - $merchantsAccountedFor; - $currentlyUseableMerchants = $currentlyNecessaryMerchants - $merchant->amount < 0 ? $currentlyNecessaryMerchants : $merchant->amount; - $merchantsAccountedFor += $currentlyUseableMerchants; - - DB::query( - <<<SQL - insert into village_units (amount, type, is_traveling, home_village_id, residence_village_id) - VALUES (:amount, :type, true, :home, :residence) - on conflict (type, home_village_id, residence_village_id, is_traveling) - do update set is_traveling=true - SQL, - [ - 'amount' => $currentlyUseableMerchants, - 'type' => 'Merchant', - 'home' => $merchant->homeVillageId, - 'residence' => $merchant->residenceVillageId, - ] - ); - DB::query('update village_units set amount=amount-:amount where id=:unitId', ['amount' => $necessaryMerchants, 'unitId' => $merchant->id]); - - DB::query( - <<<SQL - insert into events_send_resources_merchants (event_id, unit_id, amount) - VALUES (:event_id, :unit_id, :amount) - SQL, - [ - 'event_id' => $sendResourcesEventId, - 'unit_id' => $merchant->id, - 'amount' => $necessaryMerchants, - ] - ); - } - }*/ - } - - public function dbDelete(): void - { - DB::query('delete from events_send_resources_merchants where event_id=:id', ['id' => $this->id]); - } -} diff --git a/src/Model/Event/SendUnits.php b/src/Model/Event/SendUnits.php index ed4d5b6..c9afd6e 100644 --- a/src/Model/Event/SendUnits.php +++ b/src/Model/Event/SendUnits.php @@ -102,6 +102,27 @@ class SendUnits extends BaseEvent ); } + public function cancel(): void + { + $this->event = $this->getEvent(); + + $cancelTimeDiff = $this->event->createdAt->diff(new \DateTime()); + $cancelTime = (new \DateTime())->add($cancelTimeDiff); + + $this->isCanceled = true; + $this->home = $this->destination; + $this->residence = $this->source; + + DB::query( + 'update events set time=:time where id=:id', + ['time' => $cancelTime->format('c'), 'id' => $this->event->id] + ); + DB::query( + 'update events_send_units set is_canceled=:is_canceled, home=:home, residence=:residence where id=:id', + ['is_canceled' => $this->isCanceled, 'home' => $this->home, 'residence' => $this->residence, 'id' => $this->id] + ); + } + public function dbInsert(): void { DB::query( diff --git a/src/Model/Event/TrainUnits.php b/src/Model/Event/TrainUnits.php index 5e77198..59b169f 100644 --- a/src/Model/Event/TrainUnits.php +++ b/src/Model/Event/TrainUnits.php @@ -27,6 +27,11 @@ class TrainUnits extends BaseEvent ); } + public function cancel(): void + { + $this->dbDelete(); + } + public function dbInsert(): void { DB::query( diff --git a/src/Model/Event/UpgradeBuilding.php b/src/Model/Event/UpgradeBuilding.php index a426a21..a3f3984 100644 --- a/src/Model/Event/UpgradeBuilding.php +++ b/src/Model/Event/UpgradeBuilding.php @@ -3,7 +3,6 @@ namespace App\Model\Event; use App\DB; -use App\Model\Event; class UpgradeBuilding extends BaseEvent { @@ -27,6 +26,11 @@ class UpgradeBuilding extends BaseEvent ); } + public function cancel(): void + { + $this->dbDelete(); + } + public function dbInsert(): void { DB::query( diff --git a/src/Model/Unit.php b/src/Model/Unit.php index 206f5dd..d121aa7 100644 --- a/src/Model/Unit.php +++ b/src/Model/Unit.php @@ -4,6 +4,7 @@ namespace App\Model; use App\DB; use App\Model; +use App\Support\ResourceType; class Unit { @@ -20,8 +21,13 @@ class Unit public string $updatedAt; public string $buildingType; + + public int $buildTimeFactor; + public int $travelTime; + public int $populationDemandFactor; + public array $resourceRequirementsBase = []; public array $resourceRequirementsFactor = []; @@ -30,6 +36,7 @@ class Unit { $unit = new Unit(); $unit->type = $unitType; + $unit->isTraveling = false; $unit->homeVillageId = $villageId; $unit->amount = 0; @@ -45,9 +52,10 @@ class Unit return -1; } - return intval(($_ENV['BASE_UNIT_BUILD_TIME_FACTOR'] / ($building->level ?: 1)) * $amount); + return intval((($_ENV['BASE_UNIT_BUILD_TIME_FACTOR'] * $this->buildTimeFactor) / ($building->level ?: 1)) * $amount); } + public static function getTravelTime(Unit $unit, int $distance): int { return self::getTravelTimePerCell($unit) * $distance; @@ -77,7 +85,7 @@ class Unit )->fetchColumn(); $resourceRequirements = []; - foreach (['wood', 'clay', 'iron', 'food'] as $resourceType) { + foreach (ResourceType::asProperties() as $resourceType) { $base = $unit->resourceRequirementsBase[$resourceType]; $factor = $unit->resourceRequirementsFactor[$resourceType]; @@ -101,6 +109,7 @@ class Unit return $resourceRequirements; } + public function getPopulationDemand(): int { return $this->getPopulationDemandForAmount($this->amount); diff --git a/src/Model/Unit/Diplomat.php b/src/Model/Unit/Diplomat.php index baee88a..b96f3ca 100644 --- a/src/Model/Unit/Diplomat.php +++ b/src/Model/Unit/Diplomat.php @@ -7,6 +7,7 @@ use App\Model\Unit; class Diplomat extends Unit { public string $buildingType = 'Embassy'; + public int $buildTimeFactor = 10; public int $travelTime = 1; public int $populationDemandFactor = 1; diff --git a/src/Model/Unit/Farmer.php b/src/Model/Unit/Farmer.php index 5256bf1..585a1f6 100644 --- a/src/Model/Unit/Farmer.php +++ b/src/Model/Unit/Farmer.php @@ -7,6 +7,7 @@ use App\Model\Unit; class Farmer extends Unit { public string $buildingType = 'Farm'; + public int $buildTimeFactor = 1; public int $travelTime = 1; public int $populationDemandFactor = 1; diff --git a/src/Model/Unit/Merchant.php b/src/Model/Unit/MailCarrier.php index be0b25e..c787e22 100644 --- a/src/Model/Unit/Merchant.php +++ b/src/Model/Unit/MailCarrier.php @@ -5,9 +5,10 @@ namespace App\Model\Unit; use App\Model\Unit; use App\Model\Village; -class Merchant extends Unit +class MailCarrier extends Unit { - public string $buildingType = 'Marketplace'; + public string $buildingType = 'PostOffice'; + public int $buildTimeFactor = 5; public int $travelTime = 1; public int $populationDemandFactor = 1; @@ -26,8 +27,8 @@ class Merchant extends Unit public static function getResourceCapabilities(Village|int $village): int { - $marketplace = Village::getBuilding($village->id ?? $village, 'Marketplace'); + $postOffice = Village::getBuilding($village->id ?? $village, 'PostOffice'); - return $marketplace->level * 100; + return $postOffice->level * 100; } } diff --git a/src/Model/Unit/Miner.php b/src/Model/Unit/Miner.php index 06c6dda..e6a9021 100644 --- a/src/Model/Unit/Miner.php +++ b/src/Model/Unit/Miner.php @@ -7,6 +7,7 @@ use App\Model\Unit; class Miner extends Unit { public string $buildingType = 'IronMine'; + public int $buildTimeFactor = 1; public int $travelTime = 1; public int $populationDemandFactor = 1; diff --git a/src/Model/Unit/PitWorker.php b/src/Model/Unit/PitWorker.php index f2a27b6..03463b1 100644 --- a/src/Model/Unit/PitWorker.php +++ b/src/Model/Unit/PitWorker.php @@ -7,6 +7,7 @@ use App\Model\Unit; class PitWorker extends Unit { public string $buildingType = 'ClayPit'; + public int $buildTimeFactor = 1; public int $travelTime = 1; public int $populationDemandFactor = 1; diff --git a/src/Model/Unit/WoodCutter.php b/src/Model/Unit/WoodCutter.php index 02aea85..f3478b2 100644 --- a/src/Model/Unit/WoodCutter.php +++ b/src/Model/Unit/WoodCutter.php @@ -7,6 +7,7 @@ use App\Model\Unit; class WoodCutter extends Unit { public string $buildingType = 'WoodCutter'; + public int $buildTimeFactor = 1; public int $travelTime = 1; public int $populationDemandFactor = 1; diff --git a/src/Model/Village.php b/src/Model/Village.php index 019d9ba..03a57b7 100644 --- a/src/Model/Village.php +++ b/src/Model/Village.php @@ -3,7 +3,7 @@ namespace App\Model; use App\DB; -use App\Model\Building\Marketplace; +use App\Model\Building\PostOffice; use App\Model\Building\Storage; use App\Model\Village\StorageConfig; @@ -56,13 +56,13 @@ class Village public static function canSendResources(Village $village): bool { - $marketplace = Village::getBuilding($village->id, 'Marketplace'); - if (! $marketplace) { + $postOffice = Village::getBuilding($village->id, 'PostOffice'); + if (! $postOffice) { return false; } - $merchants = Village::getUnit($village, $marketplace->unitType, Village::FETCH_UNIT_RESIDENCE, Village::RETURN_UNIT_EXISTING); - if (! $merchants || $merchants->amount === 0) { + $mailCarriers = Village::getUnit($village, $postOffice->unitType, Village::FETCH_UNIT_RESIDENCE, Village::RETURN_UNIT_EXISTING); + if (! $mailCarriers || $mailCarriers->amount === 0) { return false; } @@ -89,9 +89,9 @@ class Village ); } - public static function getDistance(int $x, int $y, int $dx, int $dy): int + public static function getDistance(int $x1, int $y1, int $x2, int $y2): int { - return abs($x - $dx) + abs($y - $dy); + return abs($x1 - $x2) + abs($y1 - $y2); } /* DB - Relations */ @@ -102,7 +102,7 @@ class Village if ($withEmpty) { $nonBuiltBuildings = array_diff( - ['TownHall', 'Embassy', 'Marketplace', 'Storage', 'WoodCutter', 'ClayPit', 'IronMine', 'Farm'], + ['TownHall', 'Embassy', 'PostOffice', 'Storage', 'WoodCutter', 'ClayPit', 'IronMine', 'Farm'], array_column($buildings, 'type'), ); @@ -190,7 +190,7 @@ class Village if ($returnFlag == Village::RETURN_UNIT_ALL || $returnFlag == Village::RETURN_UNIT_TRAINABLE) { $nonExistingUnits = array_diff( - ['WoodCutter', 'PitWorker', 'Miner', 'Farmer', 'Merchant', 'Diplomat'], + ['WoodCutter', 'PitWorker', 'Miner', 'Farmer', 'MailCarrier', 'Diplomat'], array_column($units, 'type'), ); @@ -206,12 +206,25 @@ class Village } else if ($returnFlag == Village::RETURN_UNIT_EXISTING) { $units = array_filter($units, function (Unit $unit) { - return ! $unit->isTraveling; + return ! $unit->isTraveling && $unit->amount > 0; }); } - return array_map(function (Unit $unit) { + // cast + $units = array_map(function (Unit $unit) { return $unit->cast(); }, $units); + + // filter out empty traveling rows + $units = array_filter($units, function (Unit $unit) { + if ($unit->isTraveling && $unit->amount === 0) { + return false; + } + + return true; + }); + + + return $units; } } diff --git a/src/Support/ResourceType.php b/src/Support/ResourceType.php index 96c0f2c..3583824 100644 --- a/src/Support/ResourceType.php +++ b/src/Support/ResourceType.php @@ -8,4 +8,21 @@ enum ResourceType: string case Clay = 'Clay'; case Iron = 'Iron'; case Food = 'Food'; + + public static function asProperties(): array + { + return array_map(function (ResourceType $case) { + return strtolower($case->value); + }, self::cases()); + } + + public static function asPropertiesForBuildings(): array + { + $resourceTypes = self::asProperties(); + $resourceTypes = array_filter($resourceTypes, function ($resourceType) { + return $resourceType !== strtolower(self::Food->value); + }); + + return $resourceTypes; + } } diff --git a/src/gemini/Controller/Event.php b/src/gemini/Controller/Event.php new file mode 100644 index 0000000..ab4463b --- /dev/null +++ b/src/gemini/Controller/Event.php @@ -0,0 +1,55 @@ +<?php + +namespace App\gemini\Controller; + +use App\DB; +use App\Model\Event as Model; +use App\Model\Event\SendResources; +use App\Model\Event\SendUnits; +use App\Model\Event\TrainUnits; +use App\Model\Event\UpgradeBuilding; +use App\Model\Village; +use GeminiFoundation\Request; +use GeminiFoundation\Response; +use GeminiFoundation\Status; + +class Event +{ + // #[Route(path: '/event/{id}/cancel', methods: ['POST'])] + public function cancel(Request $request): Response + { + $event = DB::fetch(Model::class, 'select * from events where id=:id', ['id' => $request->get('id')])[0] ?? null; + $village = Village::get($event->villageId); + + /**@var UpgradeBuilding $upgradeBuildingEvent*/ + $upgradeBuildingEvent = DB::fetch(UpgradeBuilding::class, 'select * from events_upgrade_building where event_id=:id', ['id' => $event->id])[0] ?? null; + /**@var TrainUnits $trainUnitsEvent*/ + $trainUnitsEvent = DB::fetch(TrainUnits::class, 'select * from events_train_units where event_id=:id', ['id' => $event->id])[0] ?? null; + /**@var SendUnits $sendUnitsEvent*/ + $sendUnitsEvent = DB::fetch(SendUnits::class, 'select * from events_send_units where event_id=:id', ['id' => $event->id])[0] ?? null; + /**@var SendResources $sendResourcesEvent*/ + $sendResourcesEvent = DB::fetch(SendResources::class, 'select * from events_send_resources where event_id=:id', ['id' => $event->id])[0] ?? null; + + if (! empty($upgradeBuildingEvent)) { + $upgradeBuildingEvent->cancel(); + } + + else if (! empty($trainUnitsEvent)) { + $trainUnitsEvent->cancel(); + } + + else if (! empty($sendUnitsEvent)) { + $sendUnitsEvent->cancel(); + } + + else if (! empty($sendResourcesEvent)) { + $sendResourcesEvent->cancel(); + } + + + return new Response( + statusCode: Status::REDIRECT_TEMPORARY, + meta: "/village/{$village->x}/{$village->y}" + ); + } +} diff --git a/src/gemini/Controller/Village.php b/src/gemini/Controller/Village.php index 70aa899..81a599a 100644 --- a/src/gemini/Controller/Village.php +++ b/src/gemini/Controller/Village.php @@ -6,12 +6,14 @@ use App\DB; use App\Guard; use App\Model\Event; use App\Model\Event\SendResources; +use App\Model\Event\SendResourcesCarriers; use App\Model\Event\SendUnits; use App\Model\Event\TrainUnits; use App\Model\Event\UpgradeBuilding; use App\Model\Unit; -use App\Model\Unit\Merchant; +use App\Model\Unit\MailCarrier; use App\Model\Village as Model; +use App\Support\ResourceType; use App\View; use GeminiFoundation\Request; use GeminiFoundation\Response; @@ -113,6 +115,26 @@ class Village $events['SendResources'][] = DB::convertToModel(SendResources::class, $row);; } + $eventsResourcesCarriersSendOwn = DB::query( + <<<SQL + select * from events_send_resources_carriers as event + left join events on event.event_id = events.id + where village_id=:id + SQL, ['id' => $village->id] + )->fetchAll(); + + $eventsResourcesCarriersSendOther = DB::query( + <<<SQL + select * from events_send_resources_carriers as event + left join events on event.event_id = events.id + where (destination=:id or source=:id) and village_id!=:id + SQL, ['id' => $village->id] + )->fetchAll(); + + foreach ([...$eventsResourcesCarriersSendOwn, ...$eventsResourcesCarriersSendOther] as $row) { + $events['SendResourcesCarriers'][] = DB::convertToModel(SendResourcesCarriers::class, $row);; + } + $buildings = []; foreach (Model::getBuildings($village->id, true) as $building) { $buildings[$building->type] = $building; @@ -124,7 +146,7 @@ class Village 'events' => $events, 'buildings' => $buildings, 'villages' => DB::fetch(Model::class, "select * from villages where id!=:id", ['id' => $village->id]), - 'marketplace' => $village->getBuilding($village->id, 'Marketplace'), + 'postOffice' => $village->getBuilding($village->id, 'PostOffice'), ])); } @@ -147,7 +169,7 @@ class Village $input = intval($request->get('input')); // calculate to max 100% - $allTypes = ['wood', 'clay', 'iron', 'food']; + $allTypes = ResourceType::asProperties(); $allOtherTypes = array_diff($allTypes, [$type]); $storageConfig = $village->getStorageConfig($village->id); @@ -199,7 +221,7 @@ class Village if (empty($selectedResourceType)) { return new Response(body: View::render('send-resources/01-resource-types.twig', [ 'village' => $village, - 'marketplace' => $village->getBuilding($village->id, 'Marketplace'), + 'postOffice' => $village->getBuilding($village->id, 'PostOffice'), ])); } @@ -208,7 +230,7 @@ class Village 'village' => $village, 'villages' => DB::fetch(Model::class, "select * from villages where id!=:id", ['id' => $village->id]), 'selectedResourceType' => $selectedResourceType, - 'marketplace' => $village->getBuilding($village->id, 'Marketplace'), + 'postOffice' => $village->getBuilding($village->id, 'PostOffice'), ])); } $selectedVillage = Model::getByCoordinates($request->get('selectedVillageX'), $request->get('selectedVillageY')); @@ -218,13 +240,13 @@ class Village return new Response(statusCode: Status::INPUT, meta: 'Amount'); } - $resourceCapabilities = Merchant::getResourceCapabilities($village); - $necessaryMerchants = ceil($amount / $resourceCapabilities); - $merchants = DB::fetch(Merchant::class, 'select sum(amount) from village_units where type=:type and residence_village_id=:villageId and is_traveling=false', ['villageId' => $this->source, 'type' => 'Merchant'])[0]['amount'] ?? 0; - if ($merchants === 0) { + $resourceCapabilities = MailCarrier::getResourceCapabilities($village); + $necessaryMailCarriers = ceil($amount / $resourceCapabilities); + $mailCarriers = DB::fetch(MailCarrier::class, 'select sum(amount) as amount from village_units where type=:type and residence_village_id=:villageId and is_traveling=false', ['villageId' => $village->id, 'type' => 'MailCarrier'])[0]->amount ?? 0; + if ($mailCarriers === 0 || $amount > $resourceCapabilities) { return new Response( statusCode: Status::REDIRECT_TEMPORARY, - meta: "/village/{$village->x}/{$village->y}/type/$selectedResourceType/village/{$selectedVillage->x}/{$selectedVillage->y}" + meta: "/village/{$village->x}/{$village->y}/send-resources/type/$selectedResourceType" ); } @@ -234,7 +256,7 @@ class Village $event = new Event(); $event->time = (new \DateTime())->add( \DateInterval::createFromDateString( - Unit::getTravelTime(new Merchant(), Model::getDistance($village->x, $village->y, $destination->x, $destination->y)) + Unit::getTravelTime(new MailCarrier(), Model::getDistance($village->x, $village->y, $destination->x, $destination->y)) . ' seconds' ) ); diff --git a/src/gemini/Gemini.php b/src/gemini/Gemini.php index 4c420d4..23915d0 100644 --- a/src/gemini/Gemini.php +++ b/src/gemini/Gemini.php @@ -6,6 +6,7 @@ use App\DB; use App\EventRunner; use App\View; use App\gemini\Controller\Building; +use App\gemini\Controller\Event; use App\gemini\Controller\Unit; use App\gemini\Controller\User; use App\gemini\Controller\Village; @@ -157,6 +158,13 @@ class Gemini $response = $villageController->show($request); } + else if (preg_match('@event/(\d+)/cancel@', $request->getPath(), $routeMatch)) { + $request->set('id', $routeMatch[1]); + + $eventController = new Event(); + $response = $eventController->cancel($request); + } + return $response; }); diff --git a/src/http/Controller/Event.php b/src/http/Controller/Event.php index 070d449..46e4c22 100644 --- a/src/http/Controller/Event.php +++ b/src/http/Controller/Event.php @@ -4,7 +4,10 @@ namespace App\http\Controller; use App\DB; use App\Model\Event as Model; +use App\Model\Event\SendResources; use App\Model\Event\SendUnits; +use App\Model\Event\TrainUnits; +use App\Model\Event\UpgradeBuilding; use App\Model\Village; use App\http\Router; use Symfony\Component\HttpFoundation\RedirectResponse; @@ -31,44 +34,29 @@ class Event $event = DB::fetch(Model::class, 'select * from events where id=:id', ['id' => $request->get('id')])[0] ?? null; $village = Village::get($event->villageId); + /**@var UpgradeBuilding $upgradeBuildingEvent*/ + $upgradeBuildingEvent = DB::fetch(UpgradeBuilding::class, 'select * from events_upgrade_building where event_id=:id', ['id' => $event->id])[0] ?? null; + /**@var TrainUnits $trainUnitsEvent*/ + $trainUnitsEvent = DB::fetch(TrainUnits::class, 'select * from events_train_units where event_id=:id', ['id' => $event->id])[0] ?? null; /**@var SendUnits $sendUnitsEvent*/ $sendUnitsEvent = DB::fetch(SendUnits::class, 'select * from events_send_units where event_id=:id', ['id' => $event->id])[0] ?? null; - if (! empty($sendUnitsEvent)) { - if ($sendUnitsEvent->type === 'SendBack') { - $cancelTimeDiff = $event->createdAt->diff(new \DateTime()); - $cancelTime = (new \DateTime())->add($cancelTimeDiff); - - $sendUnitsEvent->isCanceled = true; - $sendUnitsEvent->home = $sendUnitsEvent->destination; - $sendUnitsEvent->residence = $sendUnitsEvent->source; + /**@var SendUnits $sendUnitsEvent*/ + $sendResourcesEvent = DB::fetch(SendResources::class, 'select * from events_send_resources where event_id=:id', ['id' => $event->id])[0] ?? null; - DB::query( - 'update events set time=:time where id=:id', - ['time' => $cancelTime->format('c'), 'id' => $request->get('id')] - ); - DB::query( - 'update events_send_units set is_canceled=:is_canceled, home=:home, residence=:residence where id=:id', - ['is_canceled' => $sendUnitsEvent->isCanceled, 'home' => $sendUnitsEvent->home, 'residence' => $sendUnitsEvent->residence, 'id' => $sendUnitsEvent->id] - ); - } + if (! empty($upgradeBuildingEvent)) { + $upgradeBuildingEvent->cancel(); + } - else if ($sendUnitsEvent->type === 'Recall') { - $cancelTimeDiff = $event->createdAt->diff(new \DateTime()); - $cancelTime = (new \DateTime())->add($cancelTimeDiff); + else if (! empty($trainUnitsEvent)) { + $trainUnitsEvent->cancel(); + } - $sendUnitsEvent->isCanceled = true; - $sendUnitsEvent->home = $sendUnitsEvent->destination; - $sendUnitsEvent->residence = $sendUnitsEvent->source; + else if (! empty($sendUnitsEvent)) { + $sendUnitsEvent->cancel(); + } - DB::query( - 'update events set time=:time where id=:id', - ['time' => $cancelTime->format('c'), 'id' => $request->get('id')] - ); - DB::query( - 'update events_send_units set is_canceled=:is_canceled, home=:home, residence=:residence where id=:id', - ['is_canceled' => $sendUnitsEvent->isCanceled, 'home' => $sendUnitsEvent->home, 'residence' => $sendUnitsEvent->residence, 'id' => $sendUnitsEvent->id] - ); - } + else if (! empty($sendResourcesEvent)) { + $sendResourcesEvent->cancel(); } else { |