19 declare(strict_types=1);
48 $math_tokens = $this->tokenizer->tokenizeMath($calculated_token->getValue());
50 $substituted = $this->substitution->substituteFieldValues($math_tokens);
51 [$result, $last_operator] = $this->
parseMath($substituted);
53 $from_function = $calculated_token->getFromFunction();
71 foreach ($math_tokens as $math_token) {
73 $field = $this->substitution->getFieldFromPlaceholder($math_token->getValue());
81 $tokens = $this->tokenizer->tokenize($original_token->
getValue());
82 foreach ($tokens as
$token) {
84 if (preg_match_all(
'/\[\[(.*?)\]\]/', $token->getValue(), $matches)) {
85 foreach ($matches[1] as $match) {
86 $field = $this->substitution->getFieldFromPlaceholder($match);
100 static fn(
Operators $operator):
string => $operator->value,
104 $stack =
new Stack();
105 $precedences =
new Stack();
107 foreach ($tokens as
$token) {
108 if (is_string($token)) {
113 $token = $token->getValue() ===
'' ?
'0' : $token->getValue();
115 if (is_numeric($token) || $token ===
'(') {
116 $stack->push($token);
117 if ($token ===
'(') {
120 } elseif (in_array($token, $operators)) {
122 $new_precedence = $last_operator->getPrecedence();
123 if ($new_precedence > $precedence || $in_bracket) {
125 $stack->push($token);
126 $precedences->push($new_precedence);
127 $precedence = $new_precedence;
130 while ($new_precedence <= $precedence && $stack->count() > 1) {
131 $right = (float) $stack->pop();
132 $operator = $stack->pop();
133 $left = (float) $stack->pop();
134 $result = $this->
calculate($operator, $left, $right);
135 $stack->push($result);
136 $precedence = $precedences->pop();
138 $stack->push($token);
139 $precedence = $new_precedence;
140 $precedences->push($new_precedence);
142 } elseif ($token ===
')') {
145 $elem = $stack->pop();
146 while ($elem !==
'(' && !$stack->isEmpty()) {
148 $elem = $stack->pop();
151 $stack->push($this->
parseMath(array_reverse($_tokens))[0]);
154 throw new \ilException(
"Unrecognized token '$token'");
158 if ($stack->count() === 1) {
159 $value = (
int) round((
float) $stack->pop());
160 return [$value, $last_operator ??
null];
163 while ($stack->count() >= 2) {
164 $right = $stack->pop();
165 $operator = $stack->pop();
166 $left = $stack->count() ? $stack->pop() : 0;
167 $stack->push($this->
calculate($operator, $left, $right));
169 return [$stack->pop(), $last_operator];
176 static fn(
Functions $function):
string => $function->value,
180 foreach ($functions as $function) {
181 $pattern .=
"($function)\\(([^)]*)\\)|";
183 if (!preg_match_all(rtrim($pattern,
'|') .
'#', $token->
getValue(), $result)) {
189 foreach ($result[0] as $k => $to_replace) {
191 $function = $function_args[
'function'];
192 $args = $this->substitution->substituteFieldValues($function_args[
'args']);
193 $token_value = str_replace($to_replace, (
string) $this->
calculateFunction($function, $args), $token_value);
198 Functions::tryFrom($function ??
null)
211 for ($i = 1; $i < count($data); $i++) {
213 if ($_data[$index]) {
214 $function = $_data[$index];
215 $args = explode(
';', $data[$i + 1][$index]);
216 $return[
'function'] = $function;
217 $return[
'args'] = $args;
233 $count = count($args);
234 $array_sum = array_sum($args);
236 return ($count > 0) ? $array_sum / $count : 0;
238 return array_sum($args);
244 throw new ilException(
"Unrecognized function '$function'");
255 protected function calculate(
string $operator, $left, $right)
259 $result = $left + $right;
262 $result = $left - $right;
265 $result = $left * $right;
268 $result = ($right == 0) ? 0 : $left / $right;
271 $result = pow($left, $right);
274 throw new \ilException(
"Unrecognized operator '$operator'");
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null