summaryrefslogtreecommitdiff
path: root/src/Model/Unit.php
blob: 206f5ddeff86c6793e8f81753a28a2400ce0e96f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?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 $resourceRequirementsBase = [];
  public array $resourceRequirementsFactor = [];


  public static function getEmpty(int $villageId, string $unitType): Unit
  {
    $unit = new Unit();
    $unit->type = $unitType;
    $unit->homeVillageId = $villageId;
    $unit->amount = 0;

    return $unit->cast();
  }


  public function getBuildTime(int $amount): int
  {
    $building = $this->getBuilding();

    if (! $building) {
      return -1;
    }

    return intval(($_ENV['BASE_UNIT_BUILD_TIME_FACTOR'] / ($building->level ?: 1)) * $amount);
  }

  public static function getTravelTime(Unit $unit, int $distance): int
  {
    return self::getTravelTimePerCell($unit) * $distance;
  }

  public static function getTravelTimePerCell(Unit $unit): int
  {
    return intval(ceil($unit->travelTime * $_ENV['BASE_UNIT_TRAVEL_TIME_FACTOR']));
  }


  /**
   * @return array<string, int>
   */
  public static function getResourceRequirements(Unit $unit, int $amount): array
  {
    /**@var Building $building*/
    $building = DB::fetch(
      Building::resolveType($unit->buildingType),
      'select level from village_buildings where type=:type and village_id=:id',
      ['type' => $unit->buildingType, 'id' => $unit->homeVillageId]
    )[0] ?? null;

    $currentAmount = DB::query(
      'select sum(amount) from village_units where type=:type and home_village_id=:id',
      ['type' => $unit->type, 'id' => $unit->homeVillageId]
    )->fetchColumn();

    $resourceRequirements = [];
    foreach (['wood', 'clay', 'iron', 'food'] as $resourceType) {
      $base = $unit->resourceRequirementsBase[$resourceType];
      $factor = $unit->resourceRequirementsFactor[$resourceType];

      $r = $base;
      for ($i = 0; $i <= $amount; $i++) {
        $r += ceil(
          (
            pow(
              $_ENV['BASE_UNIT_RESOURCE_REQUIREMENT_BASE'],
              $currentAmount + 1
            )
              * $factor * $_ENV['BASE_UNIT_RESOURCE_REQUIREMENT_FACTOR']
          )
            / ($building->level ?? 1)
        );
      }

      $resourceRequirements[$resourceType] = $r;
    }

    return $resourceRequirements;
  }

  public function getPopulationDemand(): int
  {
    return $this->getPopulationDemandForAmount($this->amount);
  }

  public function getPopulationDemandForAmount(int $amount): int
  {
    return $amount * $this->populationDemandFactor;
  }


  /* Relations */

  public function getHomeVillage(): Village
  {
    return DB::fetch(Village::class, 'select * from villages where id=:id', ['id' => $this->homeVillageId])[0];
  }

  public function getResidenceVillage(): Village
  {
    return DB::fetch(Village::class, 'select * from villages where id=:id', ['id' => $this->residenceVillageId])[0];
  }

  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 and is_traveling=false',
      ['type' => $unitType, 'id' => $villageId]
    );
    $result = $statement->fetch()['sum'];

    return intval($result);
  }

}