Failed Conditions
Push — master ( a2bb82...a189d9 )
by Adrien
10:27 queued 01:00
created

Trend   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Test Coverage

Coverage 29.55%

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 114
ccs 13
cts 44
cp 0.2955
rs 10
c 0
b 0
f 0
wmc 20

1 Method

Rating   Name   Duplication   Size   Complexity  
D calculate() 0 68 20
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Shared\Trend;
4
5
class Trend
6
{
7
    const TREND_LINEAR = 'Linear';
8
    const TREND_LOGARITHMIC = 'Logarithmic';
9
    const TREND_EXPONENTIAL = 'Exponential';
10
    const TREND_POWER = 'Power';
11
    const TREND_POLYNOMIAL_2 = 'Polynomial_2';
12
    const TREND_POLYNOMIAL_3 = 'Polynomial_3';
13
    const TREND_POLYNOMIAL_4 = 'Polynomial_4';
14
    const TREND_POLYNOMIAL_5 = 'Polynomial_5';
15
    const TREND_POLYNOMIAL_6 = 'Polynomial_6';
16
    const TREND_BEST_FIT = 'Bestfit';
17
    const TREND_BEST_FIT_NO_POLY = 'Bestfit_no_Polynomials';
18
19
    /**
20
     * Names of the best-fit Trend analysis methods.
21
     *
22
     * @var string[]
23
     */
24
    private static $trendTypes = [
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 $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 $trendCache = [];
50
51 45
    public static function calculate($trendType = self::TREND_BEST_FIT, $yValues = [], $xValues = [], $const = true)
52
    {
53
        //    Calculate number of points in each dataset
54 45
        $nY = count($yValues);
55 45
        $nX = count($xValues);
56
57
        //    Define X Values if necessary
58 45
        if ($nX === 0) {
59
            $xValues = range(1, $nY);
60 45
        } elseif ($nY !== $nX) {
61
            //    Ensure both arrays of points are the same size
62
            trigger_error('Trend(): Number of elements in coordinate arrays do not match.', E_USER_ERROR);
63
        }
64
65 45
        $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 45
            case self::TREND_LINEAR:
70 8
            case self::TREND_LOGARITHMIC:
71 8
            case self::TREND_EXPONENTIAL:
72
            case self::TREND_POWER:
73 45
                if (!isset(self::$trendCache[$key])) {
74 36
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
75 36
                    self::$trendCache[$key] = new $className($yValues, $xValues, $const);
76
                }
77
78 45
                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 = substr($trendType, -1);
86
                    self::$trendCache[$key] = new PolynomialBestFit($order, $yValues, $xValues);
0 ignored issues
show
Bug introduced by
$order of type string is incompatible with the type integer expected by parameter $order of PhpOffice\PhpSpreadsheet...lBestFit::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

86
                    self::$trendCache[$key] = new PolynomialBestFit(/** @scrutinizer ignore-type */ $order, $yValues, $xValues);
Loading history...
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
                $bestFit = [];
95
                $bestFitValue = [];
96
                foreach (self::$trendTypes as $trendMethod) {
97
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
98
                    $bestFit[$trendMethod] = new $className($yValues, $xValues, $const);
99
                    $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
100
                }
101
                if ($trendType != self::TREND_BEST_FIT_NO_POLY) {
102
                    foreach (self::$trendTypePolynomialOrders as $trendMethod) {
103
                        $order = substr($trendMethod, -1);
104
                        $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
                arsort($bestFitValue);
114
                $bestFitType = key($bestFitValue);
115
116
                return $bestFit[$bestFitType];
117
            default:
118
                return false;
119
        }
120
    }
121
}
122