Passed
Push — master ( 20aac0...5868f8 )
by
unknown
20:33 queued 08:57
created

Trend::calculate()   D

Complexity

Conditions 20
Paths 55

Size

Total Lines 68
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 25
CRAP Score 25.6971

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 68
ccs 25
cts 33
cp 0.7576
rs 4.1666
c 0
b 0
f 0
cc 20
nc 55
nop 4
crap 25.6971

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
namespace PhpOffice\PhpSpreadsheet\Shared\Trend;
4
5
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
6
7
class Trend
8
{
9
    const TREND_LINEAR = 'Linear';
10
    const TREND_LOGARITHMIC = 'Logarithmic';
11
    const TREND_EXPONENTIAL = 'Exponential';
12
    const TREND_POWER = 'Power';
13
    const TREND_POLYNOMIAL_2 = 'Polynomial_2';
14
    const TREND_POLYNOMIAL_3 = 'Polynomial_3';
15
    const TREND_POLYNOMIAL_4 = 'Polynomial_4';
16
    const TREND_POLYNOMIAL_5 = 'Polynomial_5';
17
    const TREND_POLYNOMIAL_6 = 'Polynomial_6';
18
    const TREND_BEST_FIT = 'Bestfit';
19
    const TREND_BEST_FIT_NO_POLY = 'Bestfit_no_Polynomials';
20
21
    /**
22
     * Names of the best-fit Trend analysis methods.
23
     */
24
    private const TREND_TYPES = [
25
        self::TREND_LINEAR,
26
        self::TREND_LOGARITHMIC,
27
        self::TREND_EXPONENTIAL,
28
        self::TREND_POWER,
29
    ];
30
31
    /**
32
     * Names of the best-fit Trend polynomial orders.
33
     *
34
     * @var string[]
35
     */
36
    private static array $trendTypePolynomialOrders = [
37
        self::TREND_POLYNOMIAL_2,
38
        self::TREND_POLYNOMIAL_3,
39
        self::TREND_POLYNOMIAL_4,
40
        self::TREND_POLYNOMIAL_5,
41
        self::TREND_POLYNOMIAL_6,
42
    ];
43
44
    /**
45
     * Cached results for each method when trying to identify which provides the best fit.
46
     *
47
     * @var BestFit[]
48
     */
49
    private static array $trendCache = [];
50
51 51
    public static function calculate(string $trendType = self::TREND_BEST_FIT, array $yValues = [], array $xValues = [], bool $const = true): BestFit
52
    {
53
        //    Calculate number of points in each dataset
54 51
        $nY = count($yValues);
55 51
        $nX = count($xValues);
56
57
        //    Define X Values if necessary
58 51
        if ($nX === 0) {
59
            $xValues = range(1, $nY);
60 51
        } elseif ($nY !== $nX) {
61
            //    Ensure both arrays of points are the same size
62 1
            throw new SpreadsheetException('Trend(): Number of elements in coordinate arrays do not match.');
63
        }
64
65 51
        $key = md5($trendType . $const . serialize($yValues) . serialize($xValues));
66
        //    Determine which Trend method has been requested
67
        switch ($trendType) {
68
            //    Instantiate and return the class for the requested Trend method
69
            case self::TREND_LINEAR:
70
            case self::TREND_LOGARITHMIC:
71
            case self::TREND_EXPONENTIAL:
72
            case self::TREND_POWER:
73 51
                if (!isset(self::$trendCache[$key])) {
74 37
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
75 37
                    self::$trendCache[$key] = new $className($yValues, $xValues, $const);
76
                }
77
78 51
                return self::$trendCache[$key];
79
            case self::TREND_POLYNOMIAL_2:
80
            case self::TREND_POLYNOMIAL_3:
81
            case self::TREND_POLYNOMIAL_4:
82
            case self::TREND_POLYNOMIAL_5:
83
            case self::TREND_POLYNOMIAL_6:
84
                if (!isset(self::$trendCache[$key])) {
85
                    $order = (int) substr($trendType, -1);
86
                    self::$trendCache[$key] = new PolynomialBestFit($order, $yValues, $xValues);
87
                }
88
89
                return self::$trendCache[$key];
90
            case self::TREND_BEST_FIT:
91
            case self::TREND_BEST_FIT_NO_POLY:
92
                //    If the request is to determine the best fit regression, then we test each Trend line in turn
93
                //    Start by generating an instance of each available Trend method
94 1
                $bestFit = [];
95 1
                $bestFitValue = [];
96 1
                foreach (self::TREND_TYPES as $trendMethod) {
97 1
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendMethod . 'BestFit';
98 1
                    $bestFit[$trendMethod] = new $className($yValues, $xValues, $const);
99 1
                    $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
100
                }
101 1
                if ($trendType !== self::TREND_BEST_FIT_NO_POLY) {
102 1
                    foreach (self::$trendTypePolynomialOrders as $trendMethod) {
103 1
                        $order = (int) substr($trendMethod, -1);
104 1
                        $bestFit[$trendMethod] = new PolynomialBestFit($order, $yValues, $xValues);
105
                        if ($bestFit[$trendMethod]->getError()) {
106
                            unset($bestFit[$trendMethod]);
107
                        } else {
108
                            $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
109
                        }
110
                    }
111
                }
112
                //    Determine which of our Trend lines is the best fit, and then we return the instance of that Trend class
113 1
                arsort($bestFitValue);
114 1
                $bestFitType = key($bestFitValue);
115
116 1
                return $bestFit[$bestFitType];
117
            default:
118 1
                throw new SpreadsheetException("Unknown trend type $trendType");
119
        }
120
    }
121
}
122