Passed
Push — main ( 28fe2f...804823 )
by mikhail
03:26
created

CDS::calculateCDS()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 8
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 11
ccs 8
cts 8
cp 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\CommentsDensity\Metrics;
6
7
use InvalidArgumentException;
8
use Mikhail\PrimitiveWrappers\Int\Integer;
9
use SavinMikhail\CommentsDensity\Comments\CommentFactory;
10
use SavinMikhail\CommentsDensity\Comments\DocBlockComment;
11
use SavinMikhail\CommentsDensity\DTO\Output\CdsDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDensity\DTO\Output\CdsDTO was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
13
use function in_array;
14
use function round;
15
16
final class CDS
17
{
18
    private const MISSING_DOCBLOCK_WEIGHT = -1;
19
20
    private bool $exceedThreshold = false;
21
22 1
    public function __construct(
23
        private readonly array $thresholds,
24
        private readonly CommentFactory $commentFactory,
25
    ) {
26 1
    }
27
28 1
    public function calculateCDS(array $commentStatistics): float
29
    {
30 1
        $rawScore = $this->calculateRawScore($commentStatistics);
31 1
        $minPossibleScore = $this->getMinPossibleScore($commentStatistics);
32 1
        $maxPossibleScore = $this->getMaxPossibleScore($commentStatistics);
33
34
        try {
35 1
            return (new Integer(0))
36 1
                ->scaleToRange($rawScore, $minPossibleScore, $maxPossibleScore);
37 1
        } catch (InvalidArgumentException $exception) {
38 1
            return 0;
39
        }
40
    }
41
42 1
    private function calculateRawScore(array $commentStatistics): float
43
    {
44 1
        $rawScore = 0;
45
46 1
        foreach ($commentStatistics as $type => $stat) {
47 1
            $comment = $this->commentFactory->getCommentType($type);
48 1
            if ($comment) {
49 1
                $rawScore += $stat['count'] * $comment->getWeight();
50 1
                continue;
51
            }
52 1
            $rawScore += $stat['count'] * self::MISSING_DOCBLOCK_WEIGHT;
53
        }
54
55 1
        return $rawScore;
56
    }
57
58 1
    private function getMinPossibleScore(array $commentStatistics): float
59
    {
60 1
        $minScore = 0;
61 1
        foreach ($commentStatistics as $type => $stat) {
62 1
            $comment = $this->commentFactory->getCommentType($type);
63 1
            if (!$comment) {
64 1
                $minScore += self::MISSING_DOCBLOCK_WEIGHT * $stat['count'];
65 1
                continue;
66
            }
67 1
            if (in_array($comment->getAttitude(), ['bad', 'unwanted'])) {
68 1
                $minScore += $comment->getWeight() * $stat['count'];
69 1
                continue;
70
            }
71 1
            $minScore -= $comment->getWeight() * $stat['count'];
72
        }
73 1
        return $minScore;
74
    }
75
76 1
    private function getMaxPossibleScore(array $commentStatistics): float
77
    {
78 1
        return (
79 1
                ($commentStatistics['missingDocblock']['count'] ?? 0)
80 1
                + ($commentStatistics['docblock']['count'] ?? 0)
81 1
            )
82 1
            * ((new DocBlockComment())->getWeight());
83
    }
84
85
    public function prepareCDS(float $cds): CdsDTO
86
    {
87
        $cds = round($cds, 2);
88
        return new CdsDTO(
89
            $cds,
90
            $this->getColorForCDS($cds),
91
        );
92
    }
93
94
    private function getColorForCDS(float $cds): string
95
    {
96
        if (! isset($this->thresholds['CDS'])) {
97
            return 'white';
98
        }
99
        if ($cds >= $this->thresholds['CDS']) {
100
            return 'green';
101
        }
102
        $this->exceedThreshold = true;
103
        return 'red';
104
    }
105
106
    public function hasExceededThreshold(): bool
107
    {
108
        return $this->exceedThreshold;
109
    }
110
}
111