Skip to content

Commit 263a397

Browse files
committed
Add test, Disable TREND_BEST_FIT, POLYNOMIAL_BEST_FIT
1 parent e496d85 commit 263a397

File tree

3 files changed

+84
-6
lines changed

3 files changed

+84
-6
lines changed

src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
namespace PhpOffice\PhpSpreadsheet\Shared\Trend;
44

55
use Matrix\Matrix;
6+
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
67

78
// Phpstan and Scrutinizer seem to have legitimate complaints.
89
// $this->slope is specified where an array is expected in several places.
910
// But it seems that it should always be float.
1011
// This code is probably not exercised at all in unit tests.
12+
// Private bool property $implemented is set to indicate
13+
// whether this implementation is correct.
1114
class PolynomialBestFit extends BestFit
1215
{
1316
/**
@@ -21,6 +24,8 @@ class PolynomialBestFit extends BestFit
2124
*/
2225
protected int $order = 0;
2326

27+
private bool $implemented = false;
28+
2429
/**
2530
* Return the order of this polynomial.
2631
*/
@@ -187,6 +192,10 @@ private function polynomialRegression(int $order, array $yValues, array $xValues
187192
*/
188193
public function __construct(int $order, array $yValues, array $xValues = [])
189194
{
195+
if (!$this->implemented) {
196+
throw new SpreadsheetException('Polynomial Best Fit not yet implemented');
197+
}
198+
190199
parent::__construct($yValues, $xValues);
191200

192201
if (!$this->error) {

src/PhpSpreadsheet/Shared/Trend/Trend.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ class Trend
1818

1919
/**
2020
* Names of the best-fit Trend analysis methods.
21-
*
22-
* @var string[]
2321
*/
24-
private static array $trendTypes = [
22+
private const TREND_TYPES = [
2523
self::TREND_LINEAR,
2624
self::TREND_LOGARITHMIC,
2725
self::TREND_EXPONENTIAL,
@@ -93,13 +91,12 @@ public static function calculate(string $trendType = self::TREND_BEST_FIT, array
9391
// Start by generating an instance of each available Trend method
9492
$bestFit = [];
9593
$bestFitValue = [];
96-
foreach (self::$trendTypes as $trendMethod) {
94+
foreach (self::TREND_TYPES as $trendMethod) {
9795
$className = '\PhpOffice\PhpSpreadsheet\Shared\Trend\\' . $trendMethod . 'BestFit';
98-
//* @phpstan-ignore-next-line
9996
$bestFit[$trendMethod] = new $className($yValues, $xValues, $const);
10097
$bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit();
10198
}
102-
if ($trendType != self::TREND_BEST_FIT_NO_POLY) {
99+
if ($trendType !== self::TREND_BEST_FIT_NO_POLY) {
103100
foreach (self::$trendTypePolynomialOrders as $trendMethod) {
104101
$order = (int) substr($trendMethod, -1);
105102
$bestFit[$trendMethod] = new PolynomialBestFit($order, $yValues, $xValues);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Shared\Trend;
6+
7+
use PhpOffice\PhpSpreadsheet\Exception as SpreadsheetException;
8+
use PhpOffice\PhpSpreadsheet\Shared\Trend\Trend;
9+
use PHPUnit\Framework\TestCase;
10+
11+
class BestFitTest extends TestCase
12+
{
13+
private const LBF_PRECISION = 1.0E-4;
14+
15+
public function testBestFit(): void
16+
{
17+
$xValues = [45, 55, 47, 75, 90, 100, 100, 95, 88, 50, 45, 58];
18+
$yValues = [15, 25, 17, 30, 41, 47, 50, 46, 37, 22, 20, 26];
19+
$maxGoodness = -1000.0;
20+
$maxType = '';
21+
22+
$type = Trend::TREND_LINEAR;
23+
$result = Trend::calculate($type, $yValues, $xValues);
24+
$goodness = $result->getGoodnessOfFit();
25+
if ($maxGoodness < $goodness) {
26+
$maxGoodness = $goodness;
27+
$maxType = $type;
28+
}
29+
self::assertEqualsWithDelta(0.9628, $goodness, self::LBF_PRECISION);
30+
31+
$type = Trend::TREND_EXPONENTIAL;
32+
$result = Trend::calculate($type, $yValues, $xValues);
33+
$goodness = $result->getGoodnessOfFit();
34+
if ($maxGoodness < $goodness) {
35+
$maxGoodness = $goodness;
36+
$maxType = $type;
37+
}
38+
self::assertEqualsWithDelta(0.9952, $goodness, self::LBF_PRECISION);
39+
40+
$type = Trend::TREND_LOGARITHMIC;
41+
$result = Trend::calculate($type, $yValues, $xValues);
42+
$goodness = $result->getGoodnessOfFit();
43+
if ($maxGoodness < $goodness) {
44+
$maxGoodness = $goodness;
45+
$maxType = $type;
46+
}
47+
self::assertEqualsWithDelta(-0.0724, $goodness, self::LBF_PRECISION);
48+
49+
$type = Trend::TREND_POWER;
50+
$result = Trend::calculate($type, $yValues, $xValues);
51+
$goodness = $result->getGoodnessOfFit();
52+
if ($maxGoodness < $goodness) {
53+
$maxGoodness = $goodness;
54+
$maxType = $type;
55+
}
56+
self::assertEqualsWithDelta(0.9946, $goodness, self::LBF_PRECISION);
57+
58+
$type = Trend::TREND_BEST_FIT_NO_POLY;
59+
$result = Trend::calculate($type, $yValues, $xValues);
60+
$goodness = $result->getGoodnessOfFit();
61+
self::assertSame($maxGoodness, $goodness);
62+
self::assertSame(lcfirst($maxType), $result->getBestFitType());
63+
64+
try {
65+
$type = Trend::TREND_BEST_FIT;
66+
$result = Trend::calculate($type, $yValues, $xValues);
67+
self::fail('should have failed - TREND_BEST_FIT includes polynomials which are not implemented yet');
68+
} catch (SpreadsheetException $e) {
69+
self::assertStringContainsString('not yet implemented', $e->getMessage());
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)