Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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 array $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 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
    public static function calculate(string $trendType = self::TREND_BEST_FIT, array $yValues = [], array $xValues = [], bool $const = true): mixed
52
    {
53
        //    Calculate number of points in each dataset
54
        $nY = count($yValues);
55
        $nX = count($xValues);
56
 
57
        //    Define X Values if necessary
58
        if ($nX === 0) {
59
            $xValues = range(1, $nY);
60
        } 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
        $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
                if (!isset(self::$trendCache[$key])) {
74
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
75
                    self::$trendCache[$key] = new $className($yValues, $xValues, $const);
76
                }
77
 
78
                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
                $bestFit = [];
95
                $bestFitValue = [];
96
                foreach (self::$trendTypes as $trendMethod) {
97
                    $className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendType . 'BestFit';
98
                    //* @phpstan-ignore-next-line
99
                    $bestFit[$trendMethod] = new $className($yValues, $xValues, $const);
100
                    $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
101
                }
102
                if ($trendType != self::TREND_BEST_FIT_NO_POLY) {
103
                    foreach (self::$trendTypePolynomialOrders as $trendMethod) {
104
                        $order = (int) substr($trendMethod, -1);
105
                        $bestFit[$trendMethod] = new PolynomialBestFit($order, $yValues, $xValues);
106
                        if ($bestFit[$trendMethod]->getError()) {
107
                            unset($bestFit[$trendMethod]);
108
                        } else {
109
                            $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
110
                        }
111
                    }
112
                }
113
                //    Determine which of our Trend lines is the best fit, and then we return the instance of that Trend class
114
                arsort($bestFitValue);
115
                $bestFitType = key($bestFitValue);
116
 
117
                return $bestFit[$bestFitType];
118
            default:
119
                return false;
120
        }
121
    }
122
}