summaryrefslogtreecommitdiff
path: root/src/Model
diff options
context:
space:
mode:
authorDaniel Weipert <code@drogueronin.de>2023-09-24 13:40:25 +0200
committerDaniel Weipert <code@drogueronin.de>2023-09-24 13:40:25 +0200
commitfa00b957378a393f8edbfc98ef111d35d18ecb09 (patch)
tree654e7dc5414f7f2795dbe996d3e1570793a5b1b8 /src/Model
initial commit
Diffstat (limited to 'src/Model')
-rw-r--r--src/Model/Building.php102
-rw-r--r--src/Model/Building/ClayPit.php16
-rw-r--r--src/Model/Building/Farm.php31
-rw-r--r--src/Model/Building/IronMine.php16
-rw-r--r--src/Model/Building/ResourceGenerator.php22
-rw-r--r--src/Model/Building/Storage.php28
-rw-r--r--src/Model/Building/TownHall.php17
-rw-r--r--src/Model/Building/WoodCutter.php16
-rw-r--r--src/Model/Event.php32
-rw-r--r--src/Model/Event/TrainUnits.php27
-rw-r--r--src/Model/Event/UpgradeBuilding.php27
-rw-r--r--src/Model/Unit.php77
-rw-r--r--src/Model/Unit/Farmer.php15
-rw-r--r--src/Model/Unit/Miner.php15
-rw-r--r--src/Model/Unit/PitWorker.php15
-rw-r--r--src/Model/Unit/WoodCutter.php15
-rw-r--r--src/Model/User.php7
-rw-r--r--src/Model/Village.php135
-rw-r--r--src/Model/Village/StorageConfig.php18
19 files changed, 631 insertions, 0 deletions
diff --git a/src/Model/Building.php b/src/Model/Building.php
new file mode 100644
index 0000000..eb166f9
--- /dev/null
+++ b/src/Model/Building.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace App\Model;
+
+use App\DB;
+use App\Model;
+
+class Building
+{
+ public int $id;
+
+ public int $level;
+ public string $type;
+ public int $villageId;
+
+ public \DateTime $createdAt;
+ public \DateTime $updatedAt;
+
+ public string $unitType;
+ public int $buildTimeFactor;
+ public array $resourceRequirements;
+ public array $buildingRequirements;
+ public array $techRequirements;
+ public int $maxLevel;
+
+
+ public static function get(int $id): ?Building
+ {
+ $results = DB::fetch(Building::class, 'select * from village_buildings where id=:id', ['id' => $id]);
+
+ return isset($results[0]) ? $results[0]->cast() : null;
+ }
+
+ public static function getByVillage(int $villageId, string $buildingType): ?Building
+ {
+ $results = DB::fetch(Building::class, 'select * from village_buildings where village_id=:id and type=:type', ['id' => $villageId, 'type' => $buildingType]);
+
+ return isset($results[0]) ? $results[0]->cast() : null;
+ }
+
+ public static function getByVillageCoordinates(int $x, int $y, string $buildingType): ?Building
+ {
+ $results = DB::fetch(
+ Building::class,
+ <<<SQL
+ select village_buildings.*
+ from village_buildings
+ join villages on (villages.x=:x and villages.y=:y)
+ where village_buildings.village_id=villages.id and type=:type
+ SQL,
+ ['x' => $x, 'y' => $y, 'type' => $buildingType]
+ );
+
+ return isset($results[0]) ? $results[0]->cast() : null;
+ }
+
+
+ public function getBuildTime(): int
+ {
+ $townHall = Village::getBuilding($this->villageId, 'TownHall');
+
+ $nextLevel = $this->level + 1;
+
+ return intval($nextLevel * ($nextLevel / $townHall->level) * $_ENV['BASE_BUILDING_BUILD_TIME_FACTOR'] * $this->buildTimeFactor);
+ }
+
+ /**
+ * @return array<string, int>
+ */
+ public function getResourceRequirements(): array
+ {
+ return $this->getResourceRequirementsForLevel($this->level);
+ }
+
+ /**
+ * @return array<string, int>
+ */
+ public function getResourceRequirementsForLevel(int $level): array
+ {
+ $level += 1;
+
+ return array_map(
+ fn ($resourceRequirement) => ceil(log($level * 2) * $resourceRequirement * 64 * $level),
+ $this->resourceRequirements
+ );
+ }
+
+
+ /* OOP */
+
+ public function cast(): Building
+ {
+ $class = Building::resolveType($this->type);
+
+ return Model::castToType($this, Building::resolveType($this->type));
+ }
+
+ public static function resolveType(string $type): string
+ {
+ return __NAMESPACE__ . '\\Building\\' . $type;
+ }
+}
diff --git a/src/Model/Building/ClayPit.php b/src/Model/Building/ClayPit.php
new file mode 100644
index 0000000..8127818
--- /dev/null
+++ b/src/Model/Building/ClayPit.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Model\Building;
+
+class ClayPit extends ResourceGenerator
+{
+ public string $unitType = 'PitWorker';
+ public int $buildTimeFactor = 1;
+ public int $maxLevel = 25;
+
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+
+ public string $resourceType = 'clay';
+}
diff --git a/src/Model/Building/Farm.php b/src/Model/Building/Farm.php
new file mode 100644
index 0000000..aaa58b5
--- /dev/null
+++ b/src/Model/Building/Farm.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace App\Model\Building;
+
+use App\Model\Unit;
+use App\Model\Village;
+
+class Farm extends ResourceGenerator
+{
+ public string $unitType = 'Farmer';
+ public int $buildTimeFactor = 1;
+ public int $maxLevel = 25;
+
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+
+ public string $resourceType = 'food';
+
+ public function getResourceIncrementor(): int
+ {
+ $populationDemand = array_reduce(
+ Village::getUnits($this->villageId, Village::FETCH_UNIT_RESIDENCE),
+ function ($carry, Unit $unit) {
+ return $carry + $unit->getPopulationDemand();
+ }
+ );
+
+ return parent::getResourceIncrementor() - $populationDemand;
+ }
+}
diff --git a/src/Model/Building/IronMine.php b/src/Model/Building/IronMine.php
new file mode 100644
index 0000000..4bf5cc6
--- /dev/null
+++ b/src/Model/Building/IronMine.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Model\Building;
+
+class IronMine extends ResourceGenerator
+{
+ public string $unitType = 'Miner';
+ public int $buildTimeFactor = 1;
+ public int $maxLevel = 25;
+
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+
+ public string $resourceType = 'iron';
+}
diff --git a/src/Model/Building/ResourceGenerator.php b/src/Model/Building/ResourceGenerator.php
new file mode 100644
index 0000000..5f1a6bb
--- /dev/null
+++ b/src/Model/Building/ResourceGenerator.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Model\Building;
+
+use App\Model\Building;
+use App\Model\Unit;
+
+class ResourceGenerator extends Building
+{
+ public string $resourceType;
+
+ public function getResourceIncrementor(): int
+ {
+ $amountResiding = Unit::getAmountResiding($this->unitType, $this->villageId);
+
+ return (int)ceil(
+ log(
+ ($this->level * $amountResiding) + 1
+ ) * $_ENV['BASE_RESOURCE_GENERATION_FACTOR']
+ );
+ }
+}
diff --git a/src/Model/Building/Storage.php b/src/Model/Building/Storage.php
new file mode 100644
index 0000000..fde4c4e
--- /dev/null
+++ b/src/Model/Building/Storage.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Model\Building;
+
+use App\Model\Building;
+use App\Model\Village;
+
+class Storage extends Building
+{
+ public int $buildTimeFactor = 1;
+ public int $maxLevel = 25;
+
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+
+ public function getCapacity(): int
+ {
+ return $this->level * 2560;
+ }
+
+ public function getResourceCapacity(string $resourceType): int
+ {
+ $p = Village::getStorageConfig($this->villageId)->$resourceType / 100;
+
+ return ceil($this->getCapacity() * $p);
+ }
+}
diff --git a/src/Model/Building/TownHall.php b/src/Model/Building/TownHall.php
new file mode 100644
index 0000000..608f083
--- /dev/null
+++ b/src/Model/Building/TownHall.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Model\Building;
+
+use App\Model\Building;
+
+class TownHall extends Building
+{
+ public int $buildTimeFactor = 1;
+ public int $maxLevel = 25;
+
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ 'clay' => 1.0,
+ 'iron' => 1.0,
+ ];
+}
diff --git a/src/Model/Building/WoodCutter.php b/src/Model/Building/WoodCutter.php
new file mode 100644
index 0000000..86bde9b
--- /dev/null
+++ b/src/Model/Building/WoodCutter.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Model\Building;
+
+class WoodCutter extends ResourceGenerator
+{
+ public string $unitType = 'WoodCutter';
+ public int $buildTimeFactor = 1;
+ public int $maxLevel = 25;
+
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+
+ public string $resourceType = 'wood';
+}
diff --git a/src/Model/Event.php b/src/Model/Event.php
new file mode 100644
index 0000000..aa235f9
--- /dev/null
+++ b/src/Model/Event.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Model;
+
+use App\Model;
+
+class Event
+{
+ public int $id;
+
+ public string $type;
+ public \DateTime $time;
+ public string $payload;
+
+ public int $villageId;
+
+
+ /* OOP */
+
+ public function cast(): Event
+ {
+ $class = Event::resolveType($this->type);
+ $object = new $class();
+
+ return Model::castToType($this, Event::resolveType($this->type));
+ }
+
+ public static function resolveType(string $type): string
+ {
+ return __NAMESPACE__ . '\\Event\\' . $type;
+ }
+}
diff --git a/src/Model/Event/TrainUnits.php b/src/Model/Event/TrainUnits.php
new file mode 100644
index 0000000..0c7e0de
--- /dev/null
+++ b/src/Model/Event/TrainUnits.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Model\Event;
+
+use App\DB;
+use App\Model\Event;
+
+class TrainUnits extends Event
+{
+ /**
+ * @return void
+ */
+ public function __invoke(): void
+ {
+ $payload = json_decode($this->payload, true);
+
+ DB::query(
+ <<<SQL
+ insert into village_units (amount, type, is_traveling, home_village_id, residence_village_id)
+ values (:amount, :type, false, :id, :id)
+ on conflict (type, home_village_id, residence_village_id)
+ do update set amount = excluded.amount+:amount
+ SQL,
+ ['amount' => $payload['amount'], 'type' => $payload['type'], 'id' => $this->villageId]
+ );
+ }
+}
diff --git a/src/Model/Event/UpgradeBuilding.php b/src/Model/Event/UpgradeBuilding.php
new file mode 100644
index 0000000..c014cfe
--- /dev/null
+++ b/src/Model/Event/UpgradeBuilding.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Model\Event;
+
+use App\DB;
+use App\Model\Event;
+
+class UpgradeBuilding extends Event
+{
+ /**
+ * @return void
+ */
+ public function __invoke(): void
+ {
+ $payload = json_decode($this->payload, true);
+
+ DB::query(
+ 'update village_buildings set level=level+1 where id=:id',
+ ['id' => $payload['id']]
+ );
+
+ DB::query(
+ 'delete from events where id=:id',
+ ['id' => $this->id]
+ );
+ }
+}
diff --git a/src/Model/Unit.php b/src/Model/Unit.php
new file mode 100644
index 0000000..a0d1a35
--- /dev/null
+++ b/src/Model/Unit.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace App\Model;
+
+use App\DB;
+use App\Model;
+
+class Unit
+{
+ public int $id;
+
+ public int $amount;
+ public string $type;
+ public bool $isTraveling;
+
+ public int $homeVillageId;
+ public int $residenceVillageId;
+
+ public string $createdAt;
+ public string $updatedAt;
+
+ public string $buildingType;
+ public int $travelTime;
+ public int $populationDemandFactor;
+ public array $resourceRequirements = [];
+
+
+ public function getBuildTime(int $amount): int
+ {
+ return intval(($_ENV['BASE_UNIT_BUILD_TIME_FACTOR'] / ($this->getBuilding()->level ?: 1)) * $amount);
+ }
+
+ public function getPopulationDemand(): int
+ {
+ return $this->getPopulationDemandForAmount($this->amount);
+ }
+
+ public function getPopulationDemandForAmount(int $amount): int
+ {
+ return $amount * $this->populationDemandFactor;
+ }
+
+
+ /* Relations */
+
+ public function getBuilding(): ?Building
+ {
+ return Village::getBuilding($this->homeVillageId, $this->buildingType);
+ }
+
+ public function cast(): Unit
+ {
+ $class = Unit::resolveType($this->type);
+
+ return Model::castToType($this, Unit::resolveType($this->type));
+ }
+
+ public static function resolveType(string $type): string
+ {
+ return __NAMESPACE__ . '\\Unit\\' . $type;
+ }
+
+
+ /* Static */
+
+ public static function getAmountResiding(string $unitType, int $villageId): int
+ {
+ $statement = DB::query(
+ 'select SUM(amount) from village_units where type=:type and residence_village_id=:id',
+ ['type' => $unitType, 'id' => $villageId]
+ );
+ $result = $statement->fetch()['sum'];
+
+ return intval($result);
+ }
+
+}
diff --git a/src/Model/Unit/Farmer.php b/src/Model/Unit/Farmer.php
new file mode 100644
index 0000000..de37802
--- /dev/null
+++ b/src/Model/Unit/Farmer.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Model\Unit;
+
+use App\Model\Unit;
+
+class Farmer extends Unit
+{
+ public string $buildingType = 'Farm';
+ public int $travelTime = 1;
+ public int $populationDemandFactor = 1;
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+}
diff --git a/src/Model/Unit/Miner.php b/src/Model/Unit/Miner.php
new file mode 100644
index 0000000..ae6c00a
--- /dev/null
+++ b/src/Model/Unit/Miner.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Model\Unit;
+
+use App\Model\Unit;
+
+class Miner extends Unit
+{
+ public string $buildingType = 'IronMine';
+ public int $travelTime = 1;
+ public int $populationDemandFactor = 1;
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+}
diff --git a/src/Model/Unit/PitWorker.php b/src/Model/Unit/PitWorker.php
new file mode 100644
index 0000000..4f873b4
--- /dev/null
+++ b/src/Model/Unit/PitWorker.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Model\Unit;
+
+use App\Model\Unit;
+
+class PitWorker extends Unit
+{
+ public string $buildingType = 'ClayPit';
+ public int $travelTime = 1;
+ public int $populationDemandFactor = 1;
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+}
diff --git a/src/Model/Unit/WoodCutter.php b/src/Model/Unit/WoodCutter.php
new file mode 100644
index 0000000..17923ca
--- /dev/null
+++ b/src/Model/Unit/WoodCutter.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Model\Unit;
+
+use App\Model\Unit;
+
+class WoodCutter extends Unit
+{
+ public string $buildingType = 'WoodCutter';
+ public int $travelTime = 1;
+ public int $populationDemandFactor = 1;
+ public array $resourceRequirements = [
+ 'wood' => 1.0,
+ ];
+}
diff --git a/src/Model/User.php b/src/Model/User.php
new file mode 100644
index 0000000..fcb1869
--- /dev/null
+++ b/src/Model/User.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace App\Model;
+
+class User
+{
+}
diff --git a/src/Model/Village.php b/src/Model/Village.php
new file mode 100644
index 0000000..cd1c749
--- /dev/null
+++ b/src/Model/Village.php
@@ -0,0 +1,135 @@
+<?php
+
+namespace App\Model;
+
+use App\DB;
+use App\Model\Building\Storage;
+use App\Model\Village\StorageConfig;
+
+class Village
+{
+ public int $id;
+
+ public string $name;
+
+ public int $x;
+ public int $y;
+
+ public int $wood;
+ public int $clay;
+ public int $iron;
+ public int $food;
+
+ public int $satisfaction;
+
+ public string $createdAt;
+ public string $updatedAt;
+
+ public static function canBuild(Village $village, Building $building): bool
+ {
+ if ($building->level >= $building->maxLevel) {
+ return false;
+ }
+
+ $resourceRequirements = $building->getResourceRequirements();
+ foreach ($resourceRequirements as $resourceType => $requirement) {
+ if ($village->$resourceType < $requirement) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /* DB - Actions */
+
+ public static function get(int $id): ?Village
+ {
+ return DB::fetch(Village::class, 'select * from villages where id=:id', ['id' => $id])[0] ?? null;
+ }
+
+ public static function getByCoordinates(int $x, int $y): ?Village
+ {
+ return DB::fetch(Village::class, 'select * from villages where x=:x and y=:y', ['x' => $x, 'y' => $y])[0] ?? null;
+ }
+
+ public function updateResources(): mixed
+ {
+ return DB::query(
+ 'update villages set wood=:wood,clay=:clay,iron=:iron,food=:food where id=:id',
+ ['wood' => $this->wood, 'clay' => $this->clay, 'iron' => $this->iron, 'food' => $this->food, 'id' => $this->id]
+ );
+ }
+
+ /* DB - Relations */
+
+ public static function getBuildings(int $villageId): array
+ {
+ $buildings = DB::fetch(Building::class, 'select * from village_buildings where village_id=:id', ['id' => $villageId]);
+
+ return array_map(function (Building $building) {
+ return $building->cast();
+ }, $buildings);
+ }
+
+ public static function getBuilding(int $villageId, string $buildingType): ?Building
+ {
+ $results = DB::fetch(
+ Building::resolveType($buildingType),
+ 'select * from village_buildings where village_id=:id and type=:type',
+ ['id' => $villageId, 'type' => $buildingType]
+ );
+
+ return isset($results[0]) ? $results[0]->cast() : null;
+ }
+
+ public static function getStorage(int $villageId): ?Storage
+ {
+ return Village::getBuilding($villageId, 'Storage');
+ }
+
+ public static function getStorageConfig(int $villageId): ?StorageConfig
+ {
+ $results = DB::fetch(
+ StorageConfig::class,
+ 'select * from village_storage_config where village_id=:id',
+ ['id' => $villageId]
+ );
+
+ return $results[0] ?? null;
+ }
+
+ public const FETCH_UNIT_HOME_AT_HOME = 1;
+ public const FETCH_UNIT_HOME_AT_SUPPORT = 2;
+ public const FETCH_UNIT_SUPPORT_AT_HOME = 3;
+ public const FETCH_UNIT_RESIDENCE = 4;
+
+ public static function getUnit(string $unitType, int $flag): ?Unit
+ {
+ }
+
+ /**
+ * @param int $flag
+ *
+ * @return array<int, Unit>
+ */
+ public static function getUnits(int $villageId, $flag = Village::FETCH_UNIT_ALL): array
+ {
+ if ($flag == Village::FETCH_UNIT_HOME_AT_HOME) {
+ $units = DB::fetch(Unit::class, 'select * from village_units where home_village_id=:id and residence_village_id=:id', ['id' => $villageId]);
+ }
+ else if ($flag == Village::FETCH_UNIT_HOME_AT_SUPPORT) {
+ $units = DB::fetch(Unit::class, 'select * from village_units where home_village_id=:id and residence_village_id!=:id', ['id' => $villageId]);
+ }
+ else if ($flag == Village::FETCH_UNIT_SUPPORT_AT_HOME) {
+ $units = DB::fetch(Unit::class, 'select * from village_units where home_village_id!=:id and residence_village_id=:id', ['id' => $villageId]);
+ }
+ else if ($flag == Village::FETCH_UNIT_RESIDENCE) {
+ $units = DB::fetch(Unit::class, 'select * from village_units where residence_village_id=:id', ['id' => $villageId]);
+ }
+
+ return array_map(function (Unit $unit) {
+ return $unit->cast();
+ }, $units);
+ }
+}
diff --git a/src/Model/Village/StorageConfig.php b/src/Model/Village/StorageConfig.php
new file mode 100644
index 0000000..272eaf5
--- /dev/null
+++ b/src/Model/Village/StorageConfig.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Model\Village;
+
+class StorageConfig
+{
+ public int $id;
+
+ public int $wood;
+ public int $clay;
+ public int $iron;
+ public int $food;
+
+ public int $villageId;
+
+ public string $createdAt;
+ public string $updatedAt;
+}