input_main); $sub_comps = Str::splitTrim($comp->input_sub); $own_hse_data = $this->getOwnHseData($comp); $subcomps_hse_data = $this->getSubcompsHseData($comp); $comp->update_success = true; $comp->save(); $moneyPi = $comp->getPropInfo('money'); $updated = false; $schedule = null; if (!is_null($comp->planner)) { /** @var \Cty\Planner $planner */ $planner = Component::resolve($comp->planner, $comp->realm); $schedule = Schedule::parse($planner->rules, $planner); } try { History::$disableAggregation = true; History::$disableHseSaveOnWrite = true; History::$disableTransactions = true; for ($t = $from_ts; $t <= $end_ts;) { // check if expression can be correctly evaluated at time $multiplierExpression = Expression::parse($comp->multiplier, $comp); $has_data = true; foreach ($multiplierExpression->getUsedPins(false) as $pin) { if ($pin->getHistorySeries()->last_time < $t) { Log::debug("Pin $pin doesnt have data for time $t"); $has_data = false; break; } } if (!$has_data) { break; } $multiplier = $multiplierExpression->evaluateAtTime($t, Type::Float); $total_increment = 0; $total_increment += $this->sumIncrement($comp, $main_comps, $subcomps_hse_data, $t); $total_increment -= $this->sumIncrement($comp, $sub_comps, $subcomps_hse_data, $t); $total_increment = $this->calcTotalIncrement($comp, $total_increment, $multiplier, $t); if (is_null($total_increment)) { break; } $actual = match ($comp->base_aggregation) { Gran::QUARTERS => $total_increment * 4, Gran::HOURS => $total_increment, Gran::DAYS => $total_increment / 24, default => throw new NotImplementedException("Bad base_aggregation: $comp->base_aggregation"), }; $actual = $this->calcActual($comp, $actual, $t); if (is_null($actual)) { break; } $changes = []; // save values to comp if ($total_increment >= 0) { $comp->total += $total_increment; $changes['total'] = $total_increment; $changes['total_production'] = 0; } else { $comp->total_production -= $total_increment; $changes['total'] = 0; $changes['total_production'] = -$total_increment; } if (is_null($schedule)) { $comp->total_t1 += $total_increment; $changes['total_t1'] = $total_increment; $changes['total_t2'] = 0; $comp->total_production_t1 -= $total_increment; $changes['total_production_t1'] = -$total_increment; $changes['total_production_t2'] = 0; } else { if ($schedule->evaluate(false, $t)) { $comp->total_t2 += $total_increment; $changes['total_t1'] = 0; $changes['total_t2'] = $total_increment; $comp->total_production_t2 -= $total_increment; $changes['total_production_t1'] = 0; $changes['total_production_t2'] = -$total_increment; } else { $comp->total_t1 += $total_increment; $changes['total_t1'] = $total_increment; $changes['total_t2'] = 0; $comp->total_production_t1 -= $total_increment; $changes['total_production_t1'] = -$total_increment; $changes['total_production_t2'] = -$total_increment; } } $comp->actual = $actual; $changes['actual'] = $actual; $next_day_ts = Tu::any2ts(Tu::any2ymd($t), true); $comp->setPropDataTimestamp('actual', $t); $t = $comp->data_timestamp = match ($comp->base_aggregation) { Gran::QUARTERS => $t + 900, Gran::HOURS => $t + 3600, Gran::DAYS => $next_day_ts, // go to next day default => throw new NotImplementedException("Bad base_aggregation: $comp->base_aggregation"), }; $comp->money += ($changes['total'] * $comp->driver()->getCumulativeMoneyConstant($comp, $moneyPi)); $this->updateDerivedProp($comp, $changes); HistWriter::writeHistory($own_hse_data, true); // force write $updated = true; } History::$disableAggregation = false; History::$disableHseSaveOnWrite = false; History::$disableTransactions = false; foreach ($own_hse_data as $hse) { $hse->save(); } HistWriter::aggregateSeriesIfNotDeferred($own_hse_data); } finally { // clear the flags even on error History::$disableAggregation = false; History::$disableHseSaveOnWrite = false; History::$disableTransactions = false; } $comp->save(); return $updated; } // ... }