summaryrefslogtreecommitdiff
path: root/src/Model/Building.php
blob: eefb4dff89d7624e4eba3f81a3fa81142e9f64f6 (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
<?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 static function getEmpty(int $villageId, string $buildingType): Building
  {
    $building = new Building();
    $building->type = $buildingType;
    $building->level = 0;
    $building->villageId = $villageId;

    return $building->cast();
  }


  public function getEffectiveLevel(): int
  {
    $upgradeEvents = DB::query(
      <<<SQL
      select * from events_upgrade_building
      inner join events on events.id = events_upgrade_building.event_id
      where events.village_id=:villageId and events_upgrade_building.type=:type
      SQL,
      ['villageId' => $this->villageId, 'type' => $this->type]
    )->fetchAll();

    return $this->level + count($upgradeEvents);
  }

  public function getBuildTime(): int
  {
    return $this->getBuildTimeForLevel($this->level + 1);
  }

  public function getBuildTimeForLevel(int $level): int
  {
    $townHall = Village::getBuilding($this->villageId, 'TownHall');

    return intval($level * ($level / $townHall->level) * $_ENV['BASE_BUILDING_BUILD_TIME_FACTOR'] * $this->buildTimeFactor);
  }

  /**
   * @return array<string, int>
   */
  public function getResourceRequirements(): array
  {
    return $this->getResourceRequirementsForLevel($this->level + 1);
  }

  /**
   * @return array<string, int>
   */
  public function getResourceRequirementsForLevel(int $level): array
  {
    return array_map(
      fn ($resourceRequirement) => ceil(log($level * 2) * $resourceRequirement * $_ENV['BASE_BUILDING_RESOURCE_REQUIREMENT_FACTOR'] * $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;
  }
}