This commit is contained in:
Thomas Peterson 2025-07-11 16:39:35 +02:00
parent 12807410f2
commit 93e6d572f9
15 changed files with 3064 additions and 2929 deletions

File diff suppressed because it is too large Load Diff

View File

@ -183,7 +183,7 @@ class Calc
$this->engine->addDebugCalcFormel($edge->getFormel(), $formel . ' = ' . $p);
$this->engine->getCalcGraph()->addCalcFormel(new Part(
type: PartType::Formel,
name: $collection->getName(),
name: sprintf('%s-%s', $option->getId(), $collection->getName()),
unParsed: $edge->getFormel(),
));
} catch (\Throwable $e) {

View File

@ -324,6 +324,22 @@ class Engine
}
}
foreach ($this->calcVariables as $key => $variable) {
if (is_array($variable)) {
$this->calcGraph->addPart(new Part(
type: PartType::CalcValue,
name: $key,
unParsed: implode(',', $variable),
));
} elseif ($variable != null) {
$this->calcGraph->addPart(new Part(
type: PartType::CalcValue,
name: $key,
unParsed: $variable,
));
}
}
$this->dirty = false;
return true;
}

View File

@ -11,8 +11,10 @@ class Calc
{
private Math $math;
public function __construct()
{
public function __construct(
private string $params,
private string $formulas,
) {
$this->math = new Math();
$this->math->suppress_errors = true;
}
@ -25,7 +27,10 @@ class Calc
foreach ($yield as $y) {
$this->parsePart($y);
$y->setResult($this->math->evaluate($y->getParsed()));
eval($this->params);
eval($this->formulas);
eval('$result = ' . $y->getParsed() . ';');
$y->setResult($result);
}
}

View File

@ -21,12 +21,12 @@ class Graph
{
$this->calcFormel = new PartCollection();
$this->parser = new Parser($formulas, $params);
$this->calc = new Calc();
$this->calc = new Calc($params, $formulas);
}
public function addCalcFormel(Part $formel): void
{
$this->calcFormel->append($formel);
$this->calcFormel->addPart($formel);
}
public function addPart(Part $part): void
@ -36,27 +36,28 @@ class Graph
private function build(): bool
{
foreach ($this->calcFormel as $formel) {
$this->parser->parseInternals();
foreach ($this->calcFormel->getData() as $formel) {
$this->parser->parse($formel);
}
foreach ($this->calcFormel as $formel) {
foreach ($this->calcFormel->getData() as $formel) {
$this->calc->calc($formel);
}
return true;
}
public function getSum(): int
public function getSum(): float
{
return array_reduce((array) $this->calcFormel, fn($sum, $item) => $sum + $item->getResult(), 0);
return round(array_reduce($this->calcFormel->getData(), fn($sum, $item) => $sum + $item->getResult(), 0), 2);
}
public function generateJsonGraph(): string
{
$this->build();
$json = [];
foreach ($this->calcFormel as $part) {
foreach ($this->calcFormel->getData() as $part) {
$json[] = $part->toArray();
}

View File

@ -5,6 +5,7 @@ namespace PSC\Library\Calc\Graph;
use PhpParser\Error;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Stmt\If_;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitorAbstract;
use PhpParser\ParserFactory;
@ -40,11 +41,15 @@ class Parser
$this->mode = $mode;
}
public function enterNode(Node $node): void
public function enterNode(Node $node): null|int
{
if ($node instanceof If_) {
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
}
if ($node instanceof Assign && $this->mode === 1) {
if ($node->expr->value != null && $node->var->name != null) {
$this->internalParts->append(new Part(
$this->internalParts->addPart(new Part(
type: PartType::Formel,
name: $node->var->name,
unParsed: (string) $node->expr->value,
@ -53,13 +58,14 @@ class Parser
}
if ($node instanceof Assign && $this->mode === 2) {
if ($node->expr->value != null && $node->var->name != null) {
$this->internalParts->append(new Part(
$this->internalParts->addPart(new Part(
type: PartType::Parameter,
name: $node->var->name,
unParsed: (string) $node->expr->value,
));
}
}
return null;
}
};
@ -67,7 +73,7 @@ class Parser
$parser = new ParserFactory()->createForNewestSupportedVersion();
try {
$ast = $parser->parse('<?php' . PHP_EOL . $formulas);
$ast = $parser->parse('<?php' . PHP_EOL . $this->formulas);
$traverser->traverse($ast);
} catch (Error $error) {
echo "Parse error: {$error->getMessage()}\n";
@ -77,7 +83,7 @@ class Parser
$visitor->setMode(2);
try {
$ast = $parser->parse('<?php' . PHP_EOL . $params);
$ast = $parser->parse('<?php' . PHP_EOL . $this->params);
$traverser->traverse($ast);
} catch (Error $error) {
echo "Parse error: {$error->getMessage()}\n";

View File

@ -44,6 +44,8 @@ class Part extends Node
return sprintf('$V%s$V', $this->name);
case PartType::CalcValue:
return sprintf('$CV%s$CV', $this->name);
default:
return $this->name;
}
}

View File

@ -4,38 +4,22 @@ namespace PSC\Library\Calc\Model;
use PSC\Library\Calc\Model\Part;
class PartCollection extends \ArrayIterator
class PartCollection
{
protected array $data = [];
public function getPartByName($string): Part|null
{
$this->rewind();
while ($this->valid()) {
if ($string == $this->current()->getFullName()) {
return $this->current();
}
$this->next();
}
return null;
return $this->data[$string] ?? null;
}
public function addPart(Part $part): void
{
$foundKey = null;
while ($this->valid()) {
if ($part->getName() == $this->current()->getName() && $part->getType() == $this->current()->getType()) {
$foundKey = $this->key();
break;
}
$this->data[$part->getFullName()] = $part;
}
$this->next();
}
if ($foundKey) {
$this->offsetSet($foundKey, $part);
} else {
$this->append($part);
}
public function getData(): array
{
return $this->data;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace PSC\Library\Calc\Tests\Customer\A;
use PHPUnit\Framework\TestCase;
use PSC\Library\Calc\Article;
use PSC\Library\Calc\Engine;
use PSC\Library\Calc\PaperContainer;
use PSC\Library\Calc\Tests\Mock\PaperRepostory;
class GraphTest extends TestCase
{
/** @var Engine */
protected $engine = null;
public function setUp(): void
{
$repository = new PaperRepostory();
$paperContainer = new PaperContainer();
$paperContainer->parse(simplexml_load_string(file_get_contents(__DIR__ . '/papierContainer.xml')));
$this->engine = new Engine();
$this->engine->setPaperContainer($paperContainer);
$this->engine->setPaperRepository($repository);
$this->engine->setFormulas(file_get_contents(__DIR__ . '/formels.txt'));
$this->engine->setParameters(file_get_contents(__DIR__ . '/parameters.txt'));
$this->engine->setTemplates(file_get_contents(__DIR__ . '/calcTemplates.xml'));
$this->engine->loadString(file_get_contents(__DIR__ . '/calc.xml'));
}
public function tearDown(): void
{
$this->engine = null;
}
public function testPriceAndGraph(): void
{
$this->engine->calc();
$priceFromOldEngine = $this->engine->getPrice();
$this->assertEquals(229.86, $priceFromOldEngine);
file_put_contents(
filename: __DIR__ . '/test.json',
data: $this->engine->getCalcGraph()->generateJsonGraph(),
);
self::assertSame($priceFromOldEngine, $this->engine->getCalcGraph()->getSum());
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,49 @@
<?php
namespace PSC\Library\Calc\Tests\Customer\B;
use PHPUnit\Framework\TestCase;
use PSC\Library\Calc\Article;
use PSC\Library\Calc\Engine;
use PSC\Library\Calc\PaperContainer;
use PSC\Library\Calc\Tests\Mock\PaperRepostory;
class GraphTest extends TestCase
{
/** @var Engine */
protected $engine = null;
public function setUp(): void
{
$repository = new PaperRepostory();
$paperContainer = new PaperContainer();
$paperContainer->parse(simplexml_load_string(file_get_contents(__DIR__ . '/papierContainer.xml')));
$this->engine = new Engine();
$this->engine->setPaperContainer($paperContainer);
$this->engine->setPaperRepository($repository);
$this->engine->setFormulas(file_get_contents(__DIR__ . '/formels.txt'));
$this->engine->setParameters(file_get_contents(__DIR__ . '/parameters.txt'));
$this->engine->setTemplates(file_get_contents(__DIR__ . '/calcTemplates.xml'));
$this->engine->loadString(file_get_contents(__DIR__ . '/calc.xml'));
}
public function tearDown(): void
{
$this->engine = null;
}
public function testPriceAndGraph(): void
{
$this->engine->calc();
$priceFromOldEngine = $this->engine->getPrice();
$this->assertEquals(945.00, $priceFromOldEngine);
file_put_contents(
filename: __DIR__ . '/test.json',
data: $this->engine->getCalcGraph()->generateJsonGraph(),
);
self::assertSame($priceFromOldEngine, $this->engine->getCalcGraph()->getSum());
}
}

View File

@ -0,0 +1 @@
[{"name":"startkosten_1c-seitenzahl_inhalt","unParsed":"$Pstartpreis_format1_52g_128$P","parsed":"945","result":945,"parts":[{"name":"startpreis_format1_52g_128","unParsed":"945","parsed":"945","result":945,"parts":[]}]},{"name":"stueckkosten_berechnung-farbigkeit_inhalt","unParsed":"($CVstueckkosten_1c_farbigkeit_inhalt$CV)*($Vauflage$V-1000)","parsed":"(0.195)*(1000-1000)","result":0,"parts":[{"name":"stueckkosten_1c_farbigkeit_inhalt","unParsed":"0.195","parsed":"0.195","result":0.195,"parts":[]},{"name":"auflage","unParsed":"1000","parsed":"1000","result":1000,"parts":[]}]},{"name":"veredelung_umschlag_kosten-veredelung_umschlag","unParsed":"0","parsed":"0","result":0,"parts":[]},{"name":"partieller_lack_umschlag_kosten-partiell_lack_umschlag","unParsed":"0","parsed":"0","result":0,"parts":[]},{"name":"papier_umschlag_kosten-papier_umschlag","unParsed":"0","parsed":"0","result":0,"parts":[]},{"name":"farbigkeit_umschlag_kosten-farbigkeit_umschlag","unParsed":"0","parsed":"0","result":0,"parts":[]},{"name":"praegung_umschlag_kosten-praegung_umschlag","unParsed":"0","parsed":"0","result":0,"parts":[]},{"name":"verpackung_kosten-verpackung","unParsed":"0","parsed":"0","result":0,"parts":[]},{"name":"belegmusterversand_kosten-belegmusterversand","unParsed":"0","parsed":"0","result":0,"parts":[]}]

View File

@ -35,7 +35,7 @@ class GraphTest extends TestCase
$this->engine = null;
}
public function tesPriceAndGraph(): void
public function testPriceAndGraph(): void
{
$this->engine->calc();
$priceFromOldEngine = $this->engine->getPrice();

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,6 @@ use PSC\Library\Calc\Model\PartType;
use function PHPUnit\Framework\assertJsonStringEqualsJsonFile;
use function PHPUnit\Framework\assertSame;
use function PHPUnit\Framework\assertTrue;
class SimpleTest extends TestCase
{
@ -37,7 +36,7 @@ class SimpleTest extends TestCase
unParsed: '$Ftest5$F+$Ftest8$F',
));
assertSame(6186, $this->graph->getSum());
assertJsonStringEqualsJsonFile(__DIR__ . '/test.json', $this->graph->generateJsonGraph());
assertSame(6186.0, $this->graph->getSum());
}
}