Total Complexity | 49 |
Total Lines | 175 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like MaskPatternTester often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use MaskPatternTester, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | final class MaskPatternTester{ |
||
26 | |||
27 | /** |
||
28 | * The data interface that contains the data matrix to test |
||
29 | */ |
||
30 | private QRData $qrData; |
||
31 | |||
32 | /** |
||
33 | * Receives the QRData object |
||
34 | * |
||
35 | * @see \chillerlan\QRCode\QROptions::$maskPattern |
||
36 | * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern |
||
37 | */ |
||
38 | public function __construct(QRData $qrData){ |
||
39 | $this->qrData = $qrData; |
||
40 | } |
||
41 | |||
42 | /** |
||
43 | * shoves a QRMatrix through the MaskPatternTester to find the lowest penalty mask pattern |
||
44 | * |
||
45 | * @see \chillerlan\QRCode\Data\MaskPatternTester |
||
46 | */ |
||
47 | public function getBestMaskPattern():MaskPattern{ |
||
48 | $penalties = []; |
||
49 | |||
50 | foreach(MaskPattern::PATTERNS as $pattern){ |
||
51 | $penalties[$pattern] = $this->testPattern(new MaskPattern($pattern)); |
||
52 | } |
||
53 | |||
54 | return new MaskPattern(array_search(min($penalties), $penalties, true)); |
||
|
|||
55 | } |
||
56 | |||
57 | /** |
||
58 | * Returns the penalty for the given mask pattern |
||
59 | * |
||
60 | * @see \chillerlan\QRCode\QROptions::$maskPattern |
||
61 | * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern |
||
62 | */ |
||
63 | public function testPattern(MaskPattern $pattern):int{ |
||
64 | $matrix = $this->qrData->writeMatrix($pattern, true); |
||
65 | $penalty = 0; |
||
66 | |||
67 | for($level = 1; $level <= 4; $level++){ |
||
68 | $penalty += call_user_func_array([$this, 'testLevel'.$level], [$matrix->matrix(true), $matrix->size()]); |
||
69 | } |
||
70 | |||
71 | return (int)$penalty; |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Checks for each group of five or more same-colored modules in a row (or column) |
||
76 | */ |
||
77 | private function testLevel1(array $m, int $size):int{ |
||
78 | $penalty = 0; |
||
79 | |||
80 | foreach($m as $y => $row){ |
||
81 | foreach($row as $x => $val){ |
||
82 | $count = 0; |
||
83 | |||
84 | for($ry = -1; $ry <= 1; $ry++){ |
||
85 | |||
86 | if($y + $ry < 0 || $size <= $y + $ry){ |
||
87 | continue; |
||
88 | } |
||
89 | |||
90 | for($rx = -1; $rx <= 1; $rx++){ |
||
91 | |||
92 | if(($ry === 0 && $rx === 0) || (($x + $rx) < 0 || $size <= ($x + $rx))){ |
||
93 | continue; |
||
94 | } |
||
95 | |||
96 | if($m[$y + $ry][$x + $rx] === $val){ |
||
97 | $count++; |
||
98 | } |
||
99 | |||
100 | } |
||
101 | } |
||
102 | |||
103 | if($count > 5){ |
||
104 | $penalty += (3 + $count - 5); |
||
105 | } |
||
106 | |||
107 | } |
||
108 | } |
||
109 | |||
110 | return $penalty; |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * Checks for each 2x2 area of same-colored modules in the matrix |
||
115 | */ |
||
116 | private function testLevel2(array $m, int $size):int{ |
||
117 | $penalty = 0; |
||
118 | |||
119 | foreach($m as $y => $row){ |
||
120 | |||
121 | if($y > $size - 2){ |
||
122 | break; |
||
123 | } |
||
124 | |||
125 | foreach($row as $x => $val){ |
||
126 | |||
127 | if($x > $size - 2){ |
||
128 | break; |
||
129 | } |
||
130 | |||
131 | if( |
||
132 | $val === $m[$y][$x + 1] |
||
133 | && $val === $m[$y + 1][$x] |
||
134 | && $val === $m[$y + 1][$x + 1] |
||
135 | ){ |
||
136 | $penalty++; |
||
137 | } |
||
138 | } |
||
139 | } |
||
140 | |||
141 | return 3 * $penalty; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Checks if there are patterns that look similar to the finder patterns (1:1:3:1:1 ratio) |
||
146 | */ |
||
147 | private function testLevel3(array $m, int $size):int{ |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Checks if more than half of the modules are dark or light, with a larger penalty for a larger difference |
||
187 | */ |
||
188 | private function testLevel4(array $m, int $size):float{ |
||
203 |