Test Failed
Push — main ( 27d416...4ff5eb )
by mikhail
03:21
created

CDS::getColorForCDS()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 1
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SavinMikhail\CommentsDensity\AnalyzeComments\Metrics;
6
7
use InvalidArgumentException;
8
use Mikhail\PrimitiveWrappers\Int\Integer;
9
use SavinMikhail\CommentsDensity\AnalyzeComments\Analyzer\DTO\Output\CdsDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDen...lyzer\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...
10
use SavinMikhail\CommentsDensity\AnalyzeComments\Analyzer\DTO\Output\CommentStatisticsDTO;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDen...ut\CommentStatisticsDTO 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...
11
use SavinMikhail\CommentsDensity\AnalyzeComments\Comments\CommentFactory;
0 ignored issues
show
Bug introduced by
The type SavinMikhail\CommentsDen...Comments\CommentFactory 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
use function in_array;
13
use function round;
14
15
final class CDS
16
{
17
    private const MISSING_DOCBLOCK_WEIGHT = -1;
18
19
    private bool $exceedThreshold = false;
20
21
    /**
22
     * @param array<string, float> $thresholds
23
     */
24
    public function __construct(
25
        private readonly array $thresholds,
26
        private readonly CommentFactory $commentFactory,
27
    ) {}
28
29
    /**
30
     * @param CommentStatisticsDTO[] $commentStatistics
31
     */
32
    public function calculateCDS(array $commentStatistics): float
33
    {
34
        $rawScore = $this->calculateRawScore($commentStatistics);
35
        $minPossibleScore = $this->getMinPossibleScore($commentStatistics);
36
        $maxPossibleScore = $this->getMaxPossibleScore($commentStatistics);
37
38
        try {
39
            return (new Integer(0))
40
                ->scaleToRange($rawScore, $minPossibleScore, $maxPossibleScore);
41
        } catch (InvalidArgumentException) {
42
            return 0;
43
        }
44
    }
45
46
    public function prepareCDS(float $cds): CdsDTO
47
    {
48
        $cds = round($cds, 2);
49
50
        return new CdsDTO(
51
            $cds,
52
            $this->getColorForCDS($cds),
53
        );
54
    }
55
56
    public function hasExceededThreshold(): bool
57
    {
58
        return $this->exceedThreshold;
59
    }
60
61
    /**
62
     * @param CommentStatisticsDTO[] $commentStatistics
63
     */
64
    private function calculateRawScore(array $commentStatistics): float
65
    {
66
        $rawScore = 0;
67
68
        foreach ($commentStatistics as $stat) {
69
            $comment = $this->commentFactory->getCommentType($stat->type);
70
            if ($comment) {
71
                $rawScore += $stat->count * $comment->getWeight();
72
73
                continue;
74
            }
75
            $rawScore += $stat->count * self::MISSING_DOCBLOCK_WEIGHT;
76
        }
77
78
        return $rawScore;
79
    }
80
81
    /**
82
     * @param CommentStatisticsDTO[] $commentStatistics
83
     */
84
    private function getMinPossibleScore(array $commentStatistics): float
85
    {
86
        $minScore = 0;
87
        foreach ($commentStatistics as $stat) {
88
            $comment = $this->commentFactory->getCommentType($stat->type);
89
            if (!$comment) {
90
                $minScore += self::MISSING_DOCBLOCK_WEIGHT * $stat->count;
91
92
                continue;
93
            }
94
            if ($comment->getWeight() < 0) {
95
                $minScore += $comment->getWeight() * $stat->count;
96
97
                continue;
98
            }
99
            $minScore -= $comment->getWeight() * $stat->count;
100
        }
101
102
        return $minScore;
103
    }
104
105
    /**
106
     * @param CommentStatisticsDTO[] $commentStatistics
107
     */
108
    private function getMaxPossibleScore(array $commentStatistics): float
109
    {
110
        $maxAmountOfDocBlock = 0;
111
        foreach ($commentStatistics as $statisticsDTO) {
112
            if (in_array($statisticsDTO->type, ['missingDocblock', 'docblock'], true)) {
113
                $maxAmountOfDocBlock += $statisticsDTO->count;
114
            }
115
        }
116
117
        return $maxAmountOfDocBlock * $this->commentFactory->getCommentType('docBlock')->getWeight();
118
    }
119
120
    private function getColorForCDS(float $cds): string
121
    {
122
        if (! isset($this->thresholds['CDS'])) {
123
            return 'white';
124
        }
125
        if ($cds >= $this->thresholds['CDS']) {
126
            return 'green';
127
        }
128
        $this->exceedThreshold = true;
129
130
        return 'red';
131
    }
132
}
133