126 lines
3.6 KiB
PHP
126 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace PSC\Library\Calc\Graph;
|
|
|
|
use PSC\Library\Calc\Model\Part;
|
|
use PSC\Library\Calc\Model\PartCollection;
|
|
use SVG\Nodes\Shapes\SVGRect;
|
|
use SVG\Nodes\Structures\SVGDocumentFragment;
|
|
use SVG\Nodes\Texts\SVGText;
|
|
use SVG\Nodes\Texts\SVGTSpan;
|
|
use SVG\SVG;
|
|
|
|
class Graph
|
|
{
|
|
protected PartCollection $calcFormel;
|
|
|
|
protected Parser $parser;
|
|
protected Calc $calc;
|
|
|
|
public function __construct(string $formulas = '', string $params = '')
|
|
{
|
|
$this->calcFormel = new PartCollection();
|
|
$this->parser = new Parser($formulas, $params);
|
|
$this->calc = new Calc($params, $formulas);
|
|
}
|
|
|
|
public function addCalcFormel(Part $formel): void
|
|
{
|
|
$this->calcFormel->addPart($formel);
|
|
}
|
|
|
|
public function addPart(Part $part): void
|
|
{
|
|
$this->parser->addPart($part);
|
|
}
|
|
|
|
private function build(): bool
|
|
{
|
|
$this->parser->parseInternals();
|
|
foreach ($this->calcFormel->getData() as $formel) {
|
|
$this->parser->parse($formel);
|
|
}
|
|
|
|
foreach ($this->calcFormel->getData() as $formel) {
|
|
$this->calc->calc($formel);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function getSum(): float
|
|
{
|
|
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->getData() as $part) {
|
|
$json[] = $part->toArray();
|
|
}
|
|
|
|
return json_encode($json);
|
|
}
|
|
|
|
public function generateSVGGraph(): string
|
|
{
|
|
$image = new SVG(1000, 1000);
|
|
$doc = $image->getDocument();
|
|
$doc->setStyle('background-color', '#ffffff');
|
|
$bg = new SVGRect(0, 0, 1000, 1000);
|
|
$bg->setAttribute('fill', '#ffffff');
|
|
$doc->addChild($bg);
|
|
$x = 20;
|
|
$y = 0;
|
|
|
|
foreach ($this->calcFormel as $formel) {
|
|
$y = $this->renderSubPart($x, $y, $doc, $formel);
|
|
}
|
|
|
|
return $image->toXMLString();
|
|
}
|
|
|
|
private function renderSubPart(int $x, int $y, SVGDocumentFragment $doc, Part $part): int
|
|
{
|
|
$y = $y + 20;
|
|
if (count($part->getChildren()) > 0) {
|
|
$textC = new SVGText('', $x, $y);
|
|
$span1 = new SVGTSpan();
|
|
$span1->setValue(sprintf('%s', $part->getName()));
|
|
$textC->addChild($span1);
|
|
|
|
$pattern = '/(\$[FPV][a-zA-Z0-9]+\$[FPV])/';
|
|
|
|
$parts = preg_split($pattern, $part->getUnparsed(), -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
|
|
|
|
foreach ($parts as $subPart) {
|
|
$child = $part->getChildrenByName($subPart);
|
|
if ($child) {
|
|
$span1 = new SVGTSpan();
|
|
$span1->setValue(sprintf('%s (%s)', $subPart, $child->getResult()));
|
|
$span1->setAttribute('dx', 10);
|
|
$span1->setAttribute('fill', $child->getColor());
|
|
$textC->addChild($span1);
|
|
$x = $x + 20;
|
|
$y = $this->renderSubPart($x, $y, $doc, $child);
|
|
} else {
|
|
$span1 = new SVGTSpan();
|
|
$span1->setValue($subPart);
|
|
$span1->setAttribute('dx', 10);
|
|
$textC->addChild($span1);
|
|
}
|
|
}
|
|
} else {
|
|
$textC = new SVGText('', $x, $y);
|
|
$span1 = new SVGTSpan();
|
|
$span1->setValue($part->getUnparsed());
|
|
$span1->setAttribute('dx', 10);
|
|
$textC->addChild($span1);
|
|
}
|
|
$doc->addChild($textC);
|
|
return $y;
|
|
}
|
|
}
|