diff --git a/src/modules/plant/run2.py b/src/modules/plant/run2.py index 0fd4a60..1ae0818 100644 --- a/src/modules/plant/run2.py +++ b/src/modules/plant/run2.py @@ -126,6 +126,42 @@ def getproyeksilinier(years, values, iterations=30, target_years=None): return {start_year + i: _predict(start_year + i) for i in range(n_projection)} +def linear_forecast_from_history(values): + """ + Melakukan proyeksi linier (OLS) dari seluruh data history. + Mengembalikan nilai forecast untuk index berikutnya. + """ + # ambil hanya nilai valid (>0) + y = [v for v in values if v is not None and v > 0] + + n = len(y) + if n == 0: + return 0.0 + if n == 1: + return y[0] # belum bisa regresi + + x = list(range(n)) + + sum_x = sum(x) + sum_y = sum(y) + sum_x2 = sum(i * i for i in x) + sum_xy = sum(i * y[i] for i in x) + + denominator = (n * sum_x2 - sum_x ** 2) + if denominator == 0: + return y[-1] + + b = (n * sum_xy - sum_x * sum_y) / denominator + a = (sum_y - b * sum_x) / n + + # forecast untuk index berikutnya + next_x = n + forecast = a + b * next_x + + # safety clamp + return max(forecast, 0.0) + + def main(): conn = get_connection() if conn is None: @@ -337,9 +373,9 @@ def main(): discount_rate = get_param("discount_rate") / 100 total_project_cost = get_param("total_project_cost") daya_mampu_netto = get_param("daya_mampu_netto") - auxiliary = get_param("auxiliary") + # auxiliary = get_param("auxiliary") susut_trafo = get_param("susut_trafo") - sfc = get_param("sfc") + # sfc = get_param("sfc") # Harga listrik berdasarkan tipe price_a = get_param("electricity_price_a") @@ -393,6 +429,8 @@ def main(): eaf_v = 0 eaf_history = [] cf_history = [] + sfc_history = [] + auxiliary_history = [] # Prefetch master data CF dan EAF sekali saja di luar loop cur.execute(""" @@ -440,7 +478,8 @@ def main(): if data["is_actual"] == 1: production_bruto = validate_number(data["production_bruto"]) production_netto = validate_number(data["production_netto"]) - energy_sales = production_netto + energy_sales = validate_number(data.get("energy_sales")) if validate_number( + data.get("energy_sales")) is not None else production_netto fuel_consumption = validate_number(data["fuel_consumption"]) revenue_a = validate_number(data["revenue_a"]) revenue_b = validate_number(data["revenue_b"]) @@ -450,7 +489,25 @@ def main(): cost_bd_om = validate_number(data["cost_bd_om"]) cost_bd_pm_nonmi = validate_number(data["cost_bd_pm_nonmi"]) cost_bd_bd = validate_number(data["cost_bd_bd"]) + + sfc_history.append(fuel_consumption / production_bruto if production_bruto != 0 else 0) + auxiliary_history.append( + (production_bruto - production_netto) / production_bruto * 100 if production_bruto != 0 else 0) else: + # last_3_sfc = sfc_history[-3:] + # avg_last_3_sfc = sum(last_3_sfc) / len(last_3_sfc) if len(last_3_sfc) > 0 else 0 + # sfc = avg_last_3_sfc + # sfc_history.append(avg_last_3_sfc) + # last_3_auxiliary = auxiliary_history[-3:] + # avg_last_3_auxiliary = sum(last_3_auxiliary) / len(last_3_auxiliary) if len(last_3_auxiliary) > 0 else 0 + # auxiliary = avg_last_3_auxiliary + # auxiliary_history.append(avg_last_3_auxiliary) + + sfc = linear_forecast_from_history(sfc_history) + sfc_history.append(sfc) + auxiliary = linear_forecast_from_history(auxiliary_history) + auxiliary_history.append(auxiliary) + production_netto = net_capacity_factor * 8760 * daya_mampu_netto / 100 production_bruto = production_netto / (100 - (auxiliary + susut_trafo)) * 100 energy_sales = production_netto