Completed
Push — master ( ef42ef...514bca )
by smiley
06:10
created

MaskPatternTester::testLevel2()   B

Complexity

Conditions 11
Paths 2

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
nc 2
nop 0
dl 0
loc 42
rs 7.3166
c 0
b 0
f 0

How to fix   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
 * Class MaskPatternTester
4
 *
5
 * @filesource   MaskPatternTester.php
6
 * @created      22.11.2017
7
 * @package      chillerlan\QRCode\Data
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2017 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\QRCode\Data;
14
15
use function abs, call_user_func;
16
17
/**
18
 * The sole purpose of this class is to receive a QRMatrix object and run the pattern tests on it.
19
 *
20
 * @link http://www.thonky.com/qr-code-tutorial/data-masking
21
 */
22
class MaskPatternTester{
23
24
	protected QRMatrix $matrix;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
25
26
	protected int $moduleCount;
27
28
	/**
29
	 * Receives the matrix an sets the module count
30
	 *
31
	 * @see \chillerlan\QRCode\QROptions::$maskPattern
32
	 * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
33
	 * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
34
	 */
35
	public function __construct(QRMatrix $matrix){
36
		$this->matrix      = $matrix;
37
		$this->moduleCount = $this->matrix->size();
38
	}
39
40
	/**
41
	 * Returns the penalty for the given mask pattern
42
	 *
43
	 * @see \chillerlan\QRCode\QROptions::$maskPattern
44
	 * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
45
	 * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
46
	 */
47
	public function testPattern():int{
48
		$penalty  = 0;
49
50
		for($level = 1; $level <= 4; $level++){
51
			$penalty += call_user_func([$this, 'testLevel'.$level]);
52
		}
53
54
		return (int)$penalty;
55
	}
56
57
	/**
58
	 * Checks for each group of five or more same-colored modules in a row (or column)
59
	 */
60
	protected function testLevel1():float{
61
		$penalty = 0;
62
63
		foreach($this->matrix->matrix() as $y => $row){
64
			foreach($row as $x => $val){
65
				$count = 0;
66
67
				for($ry = -1; $ry <= 1; $ry++){
68
69
					if($y + $ry < 0 || $this->moduleCount <= $y + $ry){
70
						continue;
71
					}
72
73
					for($rx = -1; $rx <= 1; $rx++){
74
75
						if(($ry === 0 && $rx === 0) || ($x + $rx < 0 || $this->moduleCount <= $x + $rx)){
76
							continue;
77
						}
78
79
						if($this->matrix->check($x + $rx, $y + $ry) === (($val >> 8) > 0)){
80
							$count++;
81
						}
82
83
					}
84
				}
85
86
				if($count > 5){
87
					$penalty += (3 + $count - 5);
88
				}
89
90
			}
91
		}
92
93
		return $penalty;
94
	}
95
96
	/**
97
	 * Checks for each 2x2 area of same-colored modules in the matrix
98
	 */
99
	protected function testLevel2():float{
100
		$penalty = 0;
101
102
		foreach($this->matrix->matrix() as $y => $row){
103
104
			if($y > $this->moduleCount - 2){
105
				break;
106
			}
107
108
			foreach($row as $x => $val){
109
110
				if($x > $this->moduleCount - 2){
111
					break;
112
				}
113
114
				$count = 0;
115
116
				if($val >> 8 > 0){
117
					$count++;
118
				}
119
120
				if($this->matrix->check($y, $x + 1)){
121
					$count++;
122
				}
123
124
				if($this->matrix->check($y + 1, $x)){
125
					$count++;
126
				}
127
128
				if($this->matrix->check($y + 1, $x + 1)){
129
					$count++;
130
				}
131
132
				if($count === 0 || $count === 4){
133
					$penalty += 3;
134
				}
135
136
			}
137
		}
138
139
		return $penalty;
140
	}
141
142
	/**
143
	 * Checks if there are patterns that look similar to the finder patterns
144
	 */
145
	protected function testLevel3():float{
146
		$penalty = 0;
147
148
		foreach($this->matrix->matrix() as $y => $row){
149
			foreach($row as $x => $val){
150
151
				if($x <= $this->moduleCount - 7){
152
					if(
153
						    $this->matrix->check($x    , $y)
154
						&& !$this->matrix->check($x + 1, $y)
155
						&&  $this->matrix->check($x + 2, $y)
156
						&&  $this->matrix->check($x + 3, $y)
157
						&&  $this->matrix->check($x + 4, $y)
158
						&& !$this->matrix->check($x + 5, $y)
159
						&&  $this->matrix->check($x + 6, $y)
160
					){
161
						$penalty += 40;
162
					}
163
				}
164
165
				if($y <= $this->moduleCount - 7){
166
					if(
167
						    $this->matrix->check($x, $y)
168
						&& !$this->matrix->check($x, $y + 1)
169
						&&  $this->matrix->check($x, $y + 2)
170
						&&  $this->matrix->check($x, $y + 3)
171
						&&  $this->matrix->check($x, $y + 4)
172
						&& !$this->matrix->check($x, $y + 5)
173
						&&  $this->matrix->check($x, $y + 6)
174
					){
175
						$penalty += 40;
176
					}
177
				}
178
179
			}
180
		}
181
182
		return $penalty;
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
	protected function testLevel4():float{
189
		$count = 0;
190
191
		foreach($this->matrix->matrix() as $y => $row){
192
			foreach($row as $x => $val){
193
				if($val >> 8 > 0){
194
					$count++;
195
				}
196
			}
197
		}
198
199
		return (abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
200
	}
201
202
}
203