Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
    /**
52
     * @param string $trendType
53
     * @param array $yValues
54
     * @param array $xValues
55
     * @param bool $const
56
     *
57
     * @return mixed
58
     */
59
    public static function calculate($trendType = self::TREND_BEST_FIT, $yValues = [], $xValues = [], $const = true)
60
    {
61
        //    Calculate number of points in each dataset
62
        $nY = count($yValues);
63
        $nX = count($xValues);
64
 
65
        //    Define X Values if necessary
66
        if ($nX === 0) {
67
            $xValues = range(1, $nY);
68
        } elseif ($nY !== $nX) {
69
            //    Ensure both arrays of points are the same size
70
            trigger_error('Trend(): Number of elements in coordinate arrays do not match.', E_USER_ERROR);
71
        }
72
 
73
        $key = md5($trendType . $const . serialize($yValues) . serialize($xValues));
74
        //    Determine which Trend method has been requested
75
        switch ($trendType) {
76
            //    Instantiate and return the class for the requested Trend method
77
            case self::TREND_LINEAR:
78
            case self::TREND_LOGARITHMIC:
79
            case self::TREND_EXPONENTIAL:
80
            case self::TREND_POWER:
81
                if (!isset(self::$trendCache[$key])) {
82
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
83
                    self::$trendCache[$key] = new $className($yValues, $xValues, $const);
84
                }
85
 
86
                return self::$trendCache[$key];
87
            case self::TREND_POLYNOMIAL_2:
88
            case self::TREND_POLYNOMIAL_3:
89
            case self::TREND_POLYNOMIAL_4:
90
            case self::TREND_POLYNOMIAL_5:
91
            case self::TREND_POLYNOMIAL_6:
92
                if (!isset(self::$trendCache[$key])) {
93
                    $order = (int) substr($trendType, -1);
94
                    self::$trendCache[$key] = new PolynomialBestFit($order, $yValues, $xValues);
95
                }
96
 
97
                return self::$trendCache[$key];
98
            case self::TREND_BEST_FIT:
99
            case self::TREND_BEST_FIT_NO_POLY:
100
                //    If the request is to determine the best fit regression, then we test each Trend line in turn
101
                //    Start by generating an instance of each available Trend method
102
                $bestFit = [];
103
                $bestFitValue = [];
104
                foreach (self::$trendTypes as $trendMethod) {
105
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
106
                    //* @phpstan-ignore-next-line
107
                    $bestFit[$trendMethod] = new $className($yValues, $xValues, $const);
108
                    $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
109
                }
110
                if ($trendType != self::TREND_BEST_FIT_NO_POLY) {
111
                    foreach (self::$trendTypePolynomialOrders as $trendMethod) {
112
                        $order = (int) substr($trendMethod, -1);
113
                        $bestFit[$trendMethod] = new PolynomialBestFit($order, $yValues, $xValues);
114
                        if ($bestFit[$trendMethod]->getError()) {
115
                            unset($bestFit[$trendMethod]);
116
                        } else {
117
                            $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
118
                        }
119
                    }
120
                }
121
                //    Determine which of our Trend lines is the best fit, and then we return the instance of that Trend class
122
                arsort($bestFitValue);
123
                $bestFitType = key($bestFitValue);
124
 
125
                return $bestFit[$bestFitType];
126
            default:
127
                return false;
128
        }
129
    }
130
}