This commit is contained in:
Thomas Peterson 2018-04-16 14:59:02 +02:00
parent 6dcfb6ea27
commit dceccfbd59
12 changed files with 375 additions and 68 deletions

78
src/Calc/Calc.php Normal file
View File

@ -0,0 +1,78 @@
<?php
/**
* Created by PhpStorm.
* User: thomas
* Date: 16.04.18
* Time: 14:00
*/
namespace PSC\Library\Calc\Calc;
use PSC\Library\Calc\Article;
use PSC\Library\Calc\Engine;
use PSC\Library\Calc\General\Type\Edge;
use PSC\Library\Calc\General\Type\EdgeCollection;
use PSC\Library\Calc\Option\Type\Base;
class Calc
{
/** @var Engine */
protected $engine = null;
/** @var Article */
protected $article = null;
protected $storageFormulas = [];
protected $storageCalcValues = [];
protected $formelCalc = null;
/**
* Calc constructor.
* @param Engine $engine
* @param Article $article
*/
public function __construct($engine, $article)
{
$this->engine = $engine;
$this->article = $article;
$this->formelCalc = new Formel($engine, $article);
}
public function calc()
{
$price = 0;
/** @var Base $option */
foreach($this->article->getOptions() as $option) {
/** @var EdgeCollection $collection */
foreach($option->getEdgesCollectionContainer() as $collection) {
if($collection->getFormel() != "") {
$formel = $this->formelCalc->parseVariables($collection->getFormel());
eval('$var = ' . $formel . ';');
}else{
$var = $this->engine->getVariables()[$collection->getName()];
}
/** @var Edge $edge */
foreach($collection as $edge) {
if($edge->isValid($var)) {
$formel = $this->formelCalc->parseVariables($edge->getFormel());
if ($formel != "") {
eval('$price += ' . $formel . ';');
$this->engine->setVariable('price', $price);
}
}
}
}
}
return $price;
}
}

54
src/Calc/EvalCommand.php Normal file
View File

@ -0,0 +1,54 @@
<?php
/**
* Created by PhpStorm.
* User: thomas
* Date: 13.04.18
* Time: 22:38
*/
namespace PSC\Library\Calc\Calc;
class EvalCommand
{
public function calc($formel) {
$result = 0;
eval('$result += ' . $formel . ';');
return $result;
}
private function parseVariables($formel)
{
preg_match_all('/\$V\w*\$V/', $formel, $founds);
$variables = $this->engine->getVariables();
if (!empty($founds [0])) {
foreach ($founds [0] as $key => $found) {
$foundvalue = str_replace('$V', '', $found);
if (isset($variables [$foundvalue])) {
if ($variables [$foundvalue] == 'null') {
$formel = str_replace($found, 0, $formel);
} else {
if ($foundvalue == 'auflage') {
$formel = str_replace($found, str_replace(',', '.', $variables [$foundvalue]), $formel);
} else {
if ($variables [$foundvalue] == '') {
$formel = str_replace($found, 0, $formel);
} else {
$formel = str_replace($found, $variables [$foundvalue], $formel);
}
}
}
} else {
$formel = str_replace($found, 0, $formel);
}
}
}
return $formel;
}
}

View File

@ -17,40 +17,18 @@ class Formel
/** @var Article */ /** @var Article */
protected $article = null; protected $article = null;
/**
* Calc constructor.
* @param Engine $engine
* @param Article $article
*/
public function __construct($engine, $article) public function __construct($engine, $article)
{ {
$this->engine = $engine; $this->engine = $engine;
$this->article = $article; $this->article = $article;
} }
/** public function parseVariables($formel)
* @return float
*/
public function calc()
{
$price = 0;
/** @var Base $option */
foreach($this->article->getOptions() as $option) {
/** @var EdgeCollection $collection */
foreach($option->getEdgesCollectionContainer() as $collection) {
/** @var Edge $edge */
foreach($collection as $edge) {
if($this->edgeIsValid($collection->getName(), $edge)) {
$formel = $this->parseVar($edge->getFormel());
if ($formel != "") {
eval('$price += ' . $formel . ';');
}
}
}
}
}
return $price;
}
private function parseVar($formel)
{ {
preg_match_all('/\$V\w*\$V/', $formel, $founds); preg_match_all('/\$V\w*\$V/', $formel, $founds);
@ -81,35 +59,4 @@ class Formel
return $formel; return $formel;
} }
/**
* @param $section
* @param Edge $edge
* @return bool
*/
private function edgeIsValid($section, $edge)
{
if(!isset($this->engine->getVariables()[$section])) {
return false;
}
if($edge->isRegion() &&
$edge->getFrom() <= $this->engine->getVariables()[$section] &&
$edge->getTo() >= $this->engine->getVariables()[$section]) {
return true;
}
if($edge->isRegion() &&
$edge->getFrom() <= $this->engine->getVariables()[$section] &&
$edge->getTo() == 0) {
return true;
}
if(!$edge->isRegion() && in_array($this->engine->getVariables()[$section], $edge->getValues())) {
return true;
}
return false;
}
} }

View File

@ -2,7 +2,7 @@
namespace PSC\Library\Calc; namespace PSC\Library\Calc;
use Doctrine\Common\Persistence\ObjectRepository; use Doctrine\Common\Persistence\ObjectRepository;
use PSC\Library\Calc\Calc\Formel; use PSC\Library\Calc\Calc\Calc;
use PSC\Library\Calc\Calc\Valid; use PSC\Library\Calc\Calc\Valid;
use PSC\Library\Calc\Option\Type\Base; use PSC\Library\Calc\Option\Type\Base;
use PSC\Library\Calc\Option\Type\Text; use PSC\Library\Calc\Option\Type\Text;
@ -31,6 +31,9 @@ class Engine
/** @var array */ /** @var array */
protected $variables = array(); protected $variables = array();
/** @var array */
protected $calcVariables = array();
/** @var float */ /** @var float */
protected $price = 0; protected $price = 0;
@ -85,7 +88,7 @@ class Engine
public function getArticleByName($name = false) public function getArticleByName($name = false)
{ {
if($name === false) { if($name === false) {
throw new \Exception('No Name provided'); $this->articles[0];
} }
/** @var Article $article */ /** @var Article $article */
@ -95,10 +98,6 @@ class Engine
return $article; return $article;
} }
} }
if($name === false) {
throw new \Exception('Article not found: ' . $name);
}
} }
/** /**
@ -207,8 +206,7 @@ class Engine
$calcValid->calc(); $calcValid->calc();
// CALC Formel // CALC Formel
$calcFormel = new Calc($this, $article);
$calcFormel = new Formel($this, $article);
$this->price += $calcFormel->calc(); $this->price += $calcFormel->calc();
$this->dirty = false; $this->dirty = false;
@ -234,4 +232,25 @@ class Engine
$this->price = $price; $this->price = $price;
} }
/**
* @return array
*/
public function getCalcVariables()
{
return $this->calcVariables;
}
/**
* @param array $calcVariables
*/
public function setCalcVariables($calcVariables)
{
$this->calcVariables = $calcVariables;
}
public function setVariable($var, $value)
{
$this->variables[$var] = $value;
}
} }

View File

@ -27,6 +27,10 @@ class EdgeCollection
{ {
$collection = new \PSC\Library\Calc\General\Type\EdgeCollection(); $collection = new \PSC\Library\Calc\General\Type\EdgeCollection();
if(isset($this->node->attributes()->formel)) {
$collection->setFormel((string)$this->node->attributes()->formel);
}
foreach($this->node->grenze as $row) { foreach($this->node->grenze as $row) {
$edgeParser = new Edge($row); $edgeParser = new Edge($row);
$edge = $edgeParser->parse(); $edge = $edgeParser->parse();

View File

@ -143,4 +143,29 @@ class Edge
} }
/**
* @param $value
* @return bool
*/
public function isValid($value)
{
if($this->isRegion() &&
$this->getFrom() <= $value &&
$this->getTo() >= $value) {
return true;
}
if($this->isRegion() &&
$this->getFrom() <= $value &&
$this->getTo() == 0) {
return true;
}
if(!$this->isRegion() && in_array($value, $this->getValues())) {
return true;
}
return false;
}
} }

View File

@ -5,7 +5,9 @@ namespace PSC\Library\Calc\General\Type;
class EdgeCollection extends \ArrayIterator class EdgeCollection extends \ArrayIterator
{ {
public $name = ''; protected $name = '';
protected $formel = '';
/** /**
* @return string * @return string
@ -23,5 +25,21 @@ class EdgeCollection extends \ArrayIterator
$this->name = $name; $this->name = $name;
} }
/**
* @return string
*/
public function getFormel()
{
return $this->formel;
}
/**
* @param string $formel
*/
public function setFormel($formel)
{
$this->formel = $formel;
}
} }

View File

@ -1,6 +1,7 @@
<?php <?php
namespace PSC\Library\Calc\Option; namespace PSC\Library\Calc\Option;
use PSC\Library\Calc\Option\Parser\Hidden;
use PSC\Library\Calc\Option\Parser\Input; use PSC\Library\Calc\Option\Parser\Input;
use PSC\Library\Calc\Option\Parser\Select; use PSC\Library\Calc\Option\Parser\Select;
use PSC\Library\Calc\Option\Parser\Text; use PSC\Library\Calc\Option\Parser\Text;
@ -30,6 +31,9 @@ class Parser
case 'text': case 'text':
$obj = new Text($node); $obj = new Text($node);
break; break;
case 'hidden':
$obj = new Hidden($node);
break;
} }
return $obj; return $obj;

View File

@ -0,0 +1,29 @@
<?php
namespace PSC\Library\Calc\Option\Parser;
use PSC\Library\Calc\General\Parser\EdgeCollectionContainer;
class Hidden extends Base
{
protected $element;
public function __construct(\SimpleXMLElement $node)
{
$this->element = new \PSC\Library\Calc\Option\Type\Hidden();
parent::__construct($node);
}
public function parse()
{
parent::parse();
if($this->node->children()) {
$edgeCollectionContainerParser = new EdgeCollectionContainer($this->node);
$this->element->setEdgesCollectionContainer($edgeCollectionContainerParser->parse());
}
return $this->element;
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace PSC\Library\Calc\Option\Type;
class Hidden extends Base
{
static public $type = 'hidden';
}

View File

@ -0,0 +1,53 @@
<?php
namespace PSC\Library\Calc\Tests\Calc;
use PSC\Library\Calc\Article;
use PSC\Library\Calc\Engine;
use PSC\Library\Calc\Option\Type\Base;
use PSC\Library\Calc\PaperContainer\Container;
class PriceMinTest extends \PHPUnit_Framework_TestCase
{
/** @var Engine */
protected $engine = null;
public function setUp()
{
$this->engine = new Engine(new Container());
$this->engine->loadString(file_get_contents(__DIR__ . '/../TestFiles/Calc/price_min.xml'));
}
public function tearDown()
{
$this->engine = null;
}
public function testIfArticleCountIsCorrect()
{
$this->assertEquals(1, $this->engine->getArticles()->Count());
}
public function testIfParserGetMinPrice()
{
$this->engine->calc();
$this->assertEquals(2500, $this->engine->getPrice());
}
public function testIfCalcReturnsGrenzeWithFormular()
{
$this->engine->setVariables([
'gebwert' => 1000000,
'maschwertjuengerfuenf' => 400000,
'maschwertaelterfuenf' => 400000,
'allegereate' => 400000,
'betriebsunterbrechung' => 400000,
'umsatzjahrtransport' => 300000,
'umsatzjahrbh' => 400000]);
$this->engine->calc();
$this->assertEquals(2721.40, $this->engine->getPrice());
}
}

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<kalkulation>
<artikel>
<name>test1</name>
<kommentar>test2</kommentar>
<option id="gebyn" name="Benutzen Sie ein eigenes Gebäude?" type="Select" default="1">
<opt id="1" name="Ja">
</opt>
<opt id="2" name="Nein">
</opt>
</option>
<option id="gebwert" name="Bitte geben Sie den Neuwert Ihres Gebäudes/Ihrer Gebäude ein (in Euro gerundet auf Tsd.)" type="Input" default="20000" require="true" hidden="false">
<gebyn>
<grenze formel="$Vgebwert$V/1000*0.906">1</grenze>
<grenze formel="">2</grenze>
</gebyn>
</option>
<option id="maschwertjuengerfuenf" name="Bitte addieren Sie den Wert aller in Ihrem Unternehmen eingesetzten stationären Maschinen, die&#160;&lt;b&gt;jünger als fünf Jahre&lt;/b&gt;&#160;sind (in Euro gerundet auf Tsd.)." type="Input" default="0" require="true" hidden="false">
<gebyn>
<grenze formel="$Vmaschwertjuengerfuenf$V/1000*0.900">1</grenze>
</gebyn>
</option>
<option id="maschwertaelterfuenf" name="Bitte addieren Sie den Wert aller in Ihrem Unternehmen eingesetzten stationären Maschinen, die&#160;&lt;b&gt;älter als fünf Jahre&lt;/b&gt;&#160;sind. (in Euro gerundet auf Tsd.)" type="Input" default="0" require="true" hidden="false">
<gebyn>
<grenze formel="$Vmaschwertaelterfuenf$V/1000*1.350">1-</grenze>
</gebyn>
</option>
<option id="allegereate" name="Bitte addieren Sie den Wert aller in Ihrem Unternehmen eingesetzten elektronischen Geräte, Vorräte und sonstigen Wertgegenstände, die von Bedeutung sind. (in Euro gerundet auf Tsd.)" type="Input" default="0" require="true" hidden="false">
<gebyn>
<grenze formel="$Vallegereate$V/1000*0.971">1-</grenze>
</gebyn>
</option>
<option id="betriebsunterbrechung" name="Zur Berechnung des Versicherungsschutzes für die Betriebsunterbrechung verdoppeln Sie bitte den Gesamtumsatz des vergangenen Jahres und tragen Sie den Wert in das vorgegebene Feld ein. (in Euro gerundet auf Tsd.)" type="Input" default="0" require="true" hidden="false">
<gebyn>
<grenze formel="$Vbetriebsunterbrechung$V/1000*0.590">1-</grenze>
</gebyn>
</option>
<option id="umsatzjahrtransport" name="Zur Berechnung des Versicherungsschutzes für die Transportversicherung tragen Sie bitte den Gesamtumsatz des vergangenen Jahres ein. (in Euro gerundet auf Tsd.)" type="Input" default="0" require="true" hidden="false">
<gebyn>
<grenze formel="$Vumsatzjahrtransport$V/1000*0.250">1-</grenze>
</gebyn>
</option>
<option id="umsatzjahrbh" name="Zur Berechnung des Versicherungsschutzes für die Betriebshaftpflichtversicherung tragen Sie bitte den Gesamtumsatz des vergangenen Jahres ein. (in Euro gerundet auf Tsd.)" type="Input" default="0" require="true" hidden="false">
<gebyn>
<grenze formel="$Vumsatzjahrbh$V/1000*0.540">1-</grenze>
</gebyn>
</option>
<option id="calc_min" name="" type="Hidden">
<gebyn formel="$Vprice$V &lt;= 2500? 1:2">
<grenze formel="2500-$Vprice$V">1</grenze>
<grenze formel="">2</grenze>
</gebyn>
</option>
</artikel>
</kalkulation>