LssBlockadeGrid::isVisible()   C
last analyzed

Complexity

Conditions 14
Paths 86

Size

Total Lines 55
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 36
CRAP Score 14

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 14
eloc 35
c 1
b 0
f 1
nc 86
nop 2
dl 0
loc 55
ccs 36
cts 36
cp 1
crap 14
rs 6.2666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Lib\Map\VisualPanel\LssBlockade;
6
7
use InvalidArgumentException;
8
use OutOfBoundsException;
9
10
class LssBlockadeGrid
11
{
12
    private int   $minX;
13
    private int   $minY;
14
    private int   $width;
15
    private int   $height;
16
    private int   $obsX;
17
    private int   $obsY;
18
19
    /** @var bool[][]  $blocked[$xIdx][$yIdx]   */
20
    private array $blocked  = [];
21
22 16
    public function __construct(
23
        int $minX,
24
        int $maxX,
25
        int $minY,
26
        int $maxY,
27
        int $obsX,
28
        int $obsY
29
    ) {
30 16
        if ($minX > $maxX || $minY > $maxY) {
31
            throw new InvalidArgumentException('min‑Koordinaten müssen ≤ max sein.');
32
        }
33 16
        if ($obsX < $minX || $obsX > $maxX || $obsY < $minY || $obsY > $maxY) {
34
            throw new InvalidArgumentException('Observer liegt nicht im angegebenen Rechteck.');
35
        }
36
37 16
        $this->minX  = $minX;
38 16
        $this->minY  = $minY;
39 16
        $this->width  = $maxX - $minX + 1;
40 16
        $this->height = $maxY - $minY + 1;
41 16
        $this->obsX  = $obsX;
42 16
        $this->obsY  = $obsY;
43
    }
44
45 16
    private function idxX(int $worldX): int
46
    {
47 16
        return $worldX - $this->minX;
48
    }
49 16
    private function idxY(int $worldY): int
50
    {
51 16
        return $worldY - $this->minY;
52
    }
53
54 16
    private function inRange(int $x, int $y): bool
55
    {
56 16
        return $x >= $this->minX && $x < $this->minX + $this->width
57 16
            && $y >= $this->minY && $y < $this->minY + $this->height;
58
    }
59
60 10
    public function setBlocked(int $x, int $y): void
61
    {
62 10
        if (!$this->inRange($x, $y)) {
63
            throw new OutOfBoundsException("Koordinate ($x,$y) liegt außerhalb des Grids");
64
        }
65
66 10
        $this->blocked[$this->idxX($x)][$this->idxY($y)] = true;
67
    }
68
69 16
    public function isVisible(int $x, int $y): bool
70
    {
71 16
        if (!$this->inRange($x, $y)) {
72 1
            return false;
73
        }
74
75 16
        $ixT = $this->idxX($x);
76 16
        $iyT = $this->idxY($y);
77 16
        if (!empty($this->blocked[$ixT][$iyT])) {
78 3
            return false;
79
        }
80
81 16
        $dx = $x - $this->obsX;
82 16
        $dy = $y - $this->obsY;
83 16
        $sx = $dx >= 0 ? 1 : -1;
84 16
        $sy = $dy >= 0 ? 1 : -1;
85 16
        $dx = abs($dx);
86 16
        $dy = abs($dy);
87
88 16
        $err = $dx - $dy;          // Bresenham‑Setup
89 16
        $cx  = $this->obsX;
90 16
        $cy  = $this->obsY;
91
92 16
        while ($cx !== $x || $cy !== $y) {
93
94 15
            $e2 = $err << 1;       //  = 2*err
95 15
            $nx = $cx;
96 15
            $ny = $cy;
97
98 15
            if ($e2 > -$dy) {      // Schritt in x‑Richtung
99 15
                $err -= $dy;
100 15
                $nx  += $sx;
101
            }
102 15
            if ($e2 <  $dx) {      // Schritt in y‑Richtung
103 14
                $err += $dx;
104 14
                $ny  += $sy;
105
            }
106
107 15
            if ($cx !== $nx && $cy !== $ny) {
108 14
                $side1Blocked = !empty($this->blocked[$this->idxX($cx)][$this->idxY($ny)]);
109 14
                $side2Blocked = !empty($this->blocked[$this->idxX($nx)][$this->idxY($cy)]);
110 14
                if ($side1Blocked || $side2Blocked) {
111 8
                    return false;
112
                }
113
            }
114
115 10
            if (!empty($this->blocked[$this->idxX($nx)][$this->idxY($ny)])) {
116 4
                return false;
117
            }
118
119 9
            $cx = $nx;
120 9
            $cy = $ny;
121
        }
122
123 10
        return true;
124
    }
125
}
126