Lines 100.00% 37 / 37
Methods 100.00% 10 / 10
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 socketId 100.00% 1 / 1 100.00% 1 / 1 1
 player 100.00% 1 / 1 100.00% 1 / 1 1
 location 100.00% 1 / 1 100.00% 1 / 1 1
 state 100.00% 1 / 1 100.00% 1 / 1 1
 away 100.00% 1 / 1 100.00% 1 / 1 1
 hear 100.00% 22 / 22 100.00% 1 / 1 8
 [Lorekeeper\Client\Observable] subscribe 100.00% 3 / 3 100.00% 1 / 1 2
 [Lorekeeper\Client\Observable] unsubscribe 100.00% 4 / 4 100.00% 1 / 1 1
 [Lorekeeper\Client\Observable] notify 100.00% 2 / 2 100.00% 1 / 1 2
21final class Character implements SubjectInterface
22{
23    use Observable;
24
25    public function __construct(
26        private readonly SocketId $socketId,
27        private Player $player,
28        private Location $location,
29        private CombatState $state,
30        private bool $away,
31    ) {}
32
33    public function socketId(): SocketId
34    {
35        return $this->socketId;
36    }
37
38    public function player(): Player
39    {
40        return $this->player;
41    }
42
43    public function location(): Location
44    {
45        return $this->location;
46    }
47
48    public function state(): CombatState
49    {
50        return $this->state;
51    }
52
53    public function away(): bool
54    {
55        return $this->away;
56    }
57
58    public function hear(Event $event): void
59    {
60        $me = new Identity($this->socketId, $this->player->name);
61        $was = $this->player;
62
63        $level = LevelTracking::follow($was->level, $event);
64        $vitals = VitalsTracking::follow($was->vitals, $event, $me);
65        $class = ClassTracking::follow($was->class, $event, $me);
66        $inventory = InventoryTracking::follow($was->inventory, $event);
67        $location = LocationTracking::follow($this->location, $event, $me);
68        $state = StateTracking::follow($this->state, $event, $me);
69        $away = AwayTracking::follow($this->away, $event, $me);
70
71        if (
72            $level === $was->level
73            && $vitals === $was->vitals
74            && $class === $was->class
75            && $inventory === $was->inventory
76            && $location === $this->location
77            && $state === $this->state
78            && $away === $this->away
79        ) {
80            return;
81        }
82
83        $this->player = new Player($was->name, $level, $vitals, $class, $inventory);
84        $this->location = $location;
85        $this->state = $state;
86        $this->away = $away;
87        $this->notify();
88    }
89}

From Lorekeeper\Client\Observable

11trait Observable
12{
13    /** @var list<ObserverInterface<SubjectInterface>> */
14    private array $observers = [];
15
16    /** @param ObserverInterface<SubjectInterface> $observer */
17    public function subscribe(ObserverInterface $observer): void
18    {
19        if (in_array($observer, $this->observers, strict: true)) {
20            return;
21        }
22
23        $this->observers[] = $observer;
24    }
25
26    /** @param ObserverInterface<SubjectInterface> $observer */
27    public function unsubscribe(ObserverInterface $observer): void
28    {
29        $this->observers = array_values(array_filter(
30            $this->observers,
31            static fn(ObserverInterface $subscribed): bool => $subscribed !== $observer,
32        ));
33    }
34
35    public function notify(): void
36    {
37        foreach ($this->observers as $observer) {
38            $observer->update($this);
39        }
40    }
41}