Passed
Push — master ( 50241d...54d247 )
by Jakub
09:15
created

CharacterEffect::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3.0052

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 14
ccs 11
cts 12
cp 0.9167
rs 9.8666
c 0
b 0
f 0
cc 3
nc 2
nop 1
crap 3.0052
1
<?php
2
declare(strict_types=1);
3
4
namespace HeroesofAbenez\Combat;
5
6
use Nexendrie\Utils\Constants;
7
use Symfony\Component\OptionsResolver\OptionsResolver;
8
9
/**
10
 * Data structure for effect on character
11
 *
12
 * @author Jakub Konečný
13
 * @property-read string $id
14
 * @property-read string $type
15
 * @property-read string $stat
16
 * @property-read int $value
17
 * @property-read bool $valueAbsolute
18
 * @property int|string $duration
19
 * @method void onApply(Character $character, CharacterEffect $effect)
20
 * @method void onRemove(Character $character, CharacterEffect $effect)
21
 */
22 1
class CharacterEffect {
23 1
  use \Nette\SmartObject;
24
25
  public const DURATION_COMBAT = "combat";
26
  public const DURATION_FOREVER = "forever";
27
  
28
  /** @var string */
29
  protected $id;
30
  /** @var string */
31
  protected $type;
32
  /** @var string */
33
  protected $stat = "";
34
  /** @var int */
35
  protected $value = 0;
36
  /** @var bool */
37
  protected $valueAbsolute;
38
  /** @var int|string */
39
  protected $duration;
40
  /** @var callable[] */
41
  public $onApply = [];
42
  /** @var callable[] */
43
  public $onRemove = [];
44
  
45
  public function __construct(array $effect) {
46 1
    $resolver = new OptionsResolver();
47 1
    $this->configureOptions($resolver);
48 1
    $effect = $resolver->resolve($effect);
49 1
    if(!in_array($effect["type"], SkillSpecial::NO_STAT_TYPES, true) AND $effect["stat"] === "") {
50
      throw new \InvalidArgumentException("The option stat with value '' is invalid.");
51
    }
52 1
    $this->id = $effect["id"];
53 1
    $this->type = $effect["type"];
54 1
    $this->stat = $effect["stat"];
55 1
    $this->value = $effect["value"];
56 1
    $this->valueAbsolute = $effect["valueAbsolute"];
57 1
    $this->duration = $effect["duration"];
58 1
    $this->registerDefaultHandlers();
59 1
  }
60
61
  protected function registerDefaultHandlers(): void {
62 1
    $this->onApply[] = function(Character $character, self $effect) {
63 1
      $character->recalculateStats();
64 1
      if($effect->stat === Character::STAT_MAX_HITPOINTS) {
65 1
        $character->heal($effect->value);
66
      }
67 1
    };
68 1
    $this->onRemove[] = function(Character $character, self $effect) {
69 1
      $character->recalculateStats();
70 1
      if($effect->stat === Character::STAT_MAX_HITPOINTS) {
71 1
        $character->harm($effect->value);
72
      }
73 1
    };
74 1
  }
75
76
  protected function configureOptions(OptionsResolver $resolver): void {
77 1
    $allStats = ["id", "type", "value", "valueAbsolute", "duration", "stat",];
78 1
    $resolver->setRequired($allStats);
79 1
    $resolver->setAllowedTypes("id", "string");
80 1
    $resolver->setAllowedTypes("type", "string");
81 1
    $resolver->setAllowedValues("type", function(string $value) {
82 1
      return in_array($value, $this->getAllowedTypes(), true);
83 1
    });
84 1
    $resolver->setAllowedTypes("stat", "string");
85 1
    $resolver->setDefault("stat", "");
86 1
    $resolver->setAllowedValues("stat", function(string $value) {
87 1
      return $value === "" OR in_array($value, $this->getAllowedStats(), true);
88 1
    });
89 1
    $resolver->setAllowedTypes("value", "integer");
90 1
    $resolver->setAllowedTypes("valueAbsolute", "bool");
91 1
    $resolver->setDefault("value", 0);
92 1
    $resolver->setAllowedTypes("duration", ["string", "integer"]);
93 1
    $resolver->setAllowedValues("duration", function($value) {
94 1
      return (in_array($value, $this->getDurations(), true)) OR ($value > 0);
95 1
    });
96 1
  }
97
  
98
  protected function getAllowedStats(): array {
99 1
    return Constants::getConstantsValues(Character::class, "STAT_");
100
  }
101
102
  /**
103
   * @return string[]
104
   */
105
  protected function getAllowedTypes(): array {
106 1
    return Constants::getConstantsValues(SkillSpecial::class, "TYPE_");
107
  }
108
  
109
  /**
110
   * @return string[]
111
   */
112
  protected function getDurations(): array {
113 1
    return Constants::getConstantsValues(static::class, "DURATION_");
114
  }
115
  
116
  public function getId(): string {
117 1
    return $this->id;
118
  }
119
  
120
  public function getType(): string {
121 1
    return $this->type;
122
  }
123
  
124
  public function getStat(): string {
125 1
    return $this->stat;
126
  }
127
  
128
  public function getValue(): int {
129 1
    return $this->value;
130
  }
131
132
  public function isValueAbsolute(): bool {
133 1
    return $this->valueAbsolute;
134
  }
135
136
  /**
137
   * @return int|string
138
   */
139
  public function getDuration() {
140 1
    return $this->duration;
141
  }
142
  
143
  /**
144
   * @param string|int $value
145
   * @throws \InvalidArgumentException
146
   */
147
  public function setDuration($value): void {
148 1
    if(!is_int($value) AND !in_array($value, $this->getDurations(), true)) {
149
      throw new \InvalidArgumentException("Invalid value set to CharacterEffect::\$duration. Expected string or integer.");
0 ignored issues
show
introduced by
Line exceeds 120 characters; contains 123 characters
Loading history...
150
    }
151 1
    $this->duration = $value;
152 1
  }
153
}
154
?>