import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime
if 'submitted' not in st.session_state:
st.session_state.submitted = False
st.set_page_config(page_title="Blowby Pressure & Fuel Impact Dashboard", layout="wide")
st.markdown("""
""", unsafe_allow_html=True)
def show_thank_you_message():
st.markdown("""
Terimakasih sudah simulasi
""", unsafe_allow_html=True)
if st.session_state.submitted:
show_thank_you_message()
else:
with st.sidebar:
st.markdown("⚙️ Dashboard Controls
", unsafe_allow_html=True)
st.markdown("**Developed by: Bukit Technology (RnD)**")
st.markdown(f"**Last Updated:** {datetime.now().strftime('%Y-%m-%d')}")
st.markdown("---")
st.markdown("Use this calculator to analyze blowby pressure and fuel impact for strategic decisions.")
col_logo, col_title = st.columns([1, 4])
with col_logo:
try:
st.image("buma ina.png", width=150)
except FileNotFoundError:
st.warning("⚠️ File logo 'buma_ina.PNG' tidak ditemukan. Silakan pastikan file ada di direktori yang sama dengan script.")
with col_title:
st.title("Calculator CHA for Fuel Rate Impact")
# st.markdown("**Analisis Blowby Pressure & Fuel Impact untuk Pengambilan Keputusan Strategis**")
try:
detail = pd.read_csv('1_DEV_SUMMARY_detail_data_HD785_7_ENGINE_last3month.csv')
except FileNotFoundError:
st.error("❌ File '1_DEV_SUMMARY_detail_data_HD785_7_ENGINE_last3month.csv' tidak ditemukan.")
st.stop()
st.subheader("🔍 Pilih Unit untuk Analisis")
unit_list = sorted(detail['equipment_no'].dropna().unique())
selected_unit = st.selectbox("Pilih unit number yang akan disimulasikan:", unit_list, help="Pilih nomor peralatan untuk analisis")
unit_df = detail[detail['equipment_no'] == selected_unit].sort_values("comp_life")
if unit_df.empty:
st.warning("⚠️ Data tidak tersedia untuk unit ini.")
st.stop()
current_life_df = (
detail[detail['solving_algorithm'].notna()]
.sort_values(['equipment_no', 'comp_life'])
.groupby('equipment_no')
.tail(1)
)
if selected_unit not in current_life_df['equipment_no'].values:
st.error("❌ Data current component life tidak tersedia untuk unit ini.")
st.stop()
current_life = current_life_df.loc[current_life_df['equipment_no'] == selected_unit, 'comp_life'].iloc[0]
col1, col2 = st.columns([2, 1])
with col1:
st.subheader("📊 Grafik Blowby Pressure terhadap Umur Komponen")
max_life = unit_df['comp_life'].max()
fig = px.line(unit_df, x='comp_life', y='blowby_press_max_act',
title=f"Unit: {selected_unit}",
labels={'comp_life': 'Component Life (Hours)', 'blowby_press_max_act': 'Pressure (mmH2O)'},
line_shape='linear', render_mode='svg')
fig.add_vline(x=current_life, line_dash="dash", line_color="#7f8c8d", annotation_text="Current Life", annotation_position="top left")
fig.update_traces(line_color='#1abc9c', line_width=3, marker=dict(size=8))
fig.update_layout(
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)',
font=dict(family="Poppins", size=12, color="#ecf0f1"),
title_font=dict(size=18, color="#f1c40f"),
showlegend=True,
xaxis=dict(showgrid=True, gridcolor='rgba(255,255,255,0.2)'),
yaxis=dict(showgrid=True, gridcolor='rgba(255,255,255,0.2)')
)
st.plotly_chart(fig, use_container_width=True)
with col2:
st.subheader("⏳ Current Component Life")
st.markdown(f"""
Current Life
{current_life:,.0f} jam
""", unsafe_allow_html=True)
st.subheader("⚙️ Simulasi Perpanjangan Umur Komponen")
input_method = st.radio("Pilih metode input:", ["Slider", "Input Numerik"], horizontal=True)
max_deviation = int(max_life - current_life)
if input_method == "Slider":
extended_life = st.slider(
"Simulasikan Perpanjangan Umur Komponen Hingga (jam):",
min_value=int(current_life + 100),
max_value=int(max_life),
value=int(min(current_life + 1000, max_life)),
step=100,
help="Geser untuk memilih umur komponen yang diinginkan"
)
deviation = extended_life - current_life
else:
deviation = st.number_input(
"Masukkan Perpanjangan Umur Komponen Sebesar (jam):",
min_value=100,
max_value=max_deviation,
value=min(1000, max_deviation),
step=100,
help="Masukkan jumlah jam perpanjangan dari current life"
)
extended_life = current_life + deviation
st.markdown(f"**Umur Komponen Diperpanjang Hingga:** {extended_life:,.0f} jam (Perpanjangan: {deviation:,.0f} jam)", unsafe_allow_html=True)
sim_df = unit_df[(unit_df['comp_life'] > current_life) & (unit_df['comp_life'] <= extended_life)]
def hitung_avg_blowby(df, batas):
tmp = df[['comp_life', 'blowby_press_max_act']].dropna().sort_values('comp_life')
tmp = tmp[tmp['comp_life'] <= batas]
if tmp.empty:
return 0
tail = tmp.tail(10)
if len(tail) < 10:
st.warning(f"Hanya {len(tail)} titik data (<= {batas} jam).")
return tail['blowby_press_max_act'].mean()
def hitung_avg_blowbyawal(df, batas):
tmp = df[['comp_life', 'blowby_press_max_act']].dropna().sort_values('comp_life')
tmp = tmp[tmp['comp_life'] <= batas]
if tmp.empty:
return 0
tail = tmp.tail(30)
if len(tail) < 30:
st.warning(f"Hanya {len(tail)} titik data (<= {batas} jam).")
return tail['blowby_press_max_act'].mean()
def fuel_awal_data(df, batas):
tmp = df[['comp_life', 'fuel_rate_act']].dropna().sort_values('comp_life')
tmp = tmp[tmp['comp_life'] <= batas]
if tmp.empty:
return 0
tail = tmp.tail(5)
if len(tail) < 5:
st.warning(f"Hanya {len(tail)} titik data (<= {batas} jam).")
return tail['fuel_rate_act'].mean()
def fuel_awal_setelah_replacement(df, batas):
tmp = df[['comp_life', 'fuel_rate_act']].dropna().sort_values('comp_life')
tmp = tmp[tmp['comp_life'] <= batas]
if tmp.empty:
return 0
head = tmp.head(5)
if len(head) < 5:
st.warning(f"Hanya {len(head)} titik data (<= {batas} jam).")
return head['fuel_rate_act'].mean()
st.subheader("⛽ Prediksi Fuel Rate")
avg_blowby_awal = fuel_awal_data(unit_df, current_life)
avg_blowby_akhir = hitung_avg_blowby(unit_df, extended_life)
fuel_setelah_replacement =fuel_awal_setelah_replacement(unit_df, extended_life)
delta_life = extended_life - current_life
fuel_rate_awal = (avg_blowby_awal * 0.004) + 71.86 # L/h
fuel_rate_akhir = (avg_blowby_akhir * 0.004) + 71.86 # L/h
hours_ext = extended_life - current_life
fuel_usage = fuel_rate_akhir * hours_ext # total L over extension
col3, col4, col5 = st.columns(3)
with col3:
st.markdown(f"""
Fuel Rate Terakhir
{fuel_rate_awal:.2f} L/h
""", unsafe_allow_html=True)
with col4:
st.markdown(f"""
Fuel Akumulasi
{(fuel_rate_akhir * delta_life):,.2f} L
""", unsafe_allow_html=True)
with col5:
st.markdown(f"""
Total Extend
{delta_life:,.2f} Hm
""", unsafe_allow_html=True)
if not sim_df.empty and sim_df['trendline_blow'].notna().any():
last_f = sim_df['trendline_blow'].dropna().iloc[-1]
fr_f = last_f * 0.004 + 71.86
rpm_f = last_f * 0.034 + 1303.75
col6, col7 = st.columns(2)
with col6:
st.markdown(f"""
Fuel Rate Forecast
{fr_f:.2f} L/h
""", unsafe_allow_html=True)
with col7:
st.markdown(f"""
Engine Speed Forecast
{rpm_f:.2f} RPM
""", unsafe_allow_html=True)
st.subheader("💰 Analisis Keuntungan dan Kerugian")
harga_engine = 110_000 # USD
harga_fuel = 1 # USD/L
cost_per_h = harga_engine / current_life
saving = ((cost_per_h * delta_life) + (fuel_setelah_replacement* delta_life))
fuel_cost = fuel_usage * harga_fuel
net_savings = fuel_cost - saving
col8, col9, col10 = st.columns(3)
with col8:
st.markdown(f"""
Cost Replacement
USD {saving:,.2f}
""", unsafe_allow_html=True)
with col9:
st.markdown(f"""
Cost Fuel (Extend)
USD {fuel_cost:,.2f}
""", unsafe_allow_html=True)
with col10:
st.markdown(f"""
Net Savings
USD {net_savings:,.2f}
""", unsafe_allow_html=True)
st.subheader("Perbandingan Penghematan vs Biaya Fuel")
fig2 = go.Figure()
fig2.add_trace(go.Bar(
x=[saving, fuel_cost],
y=["Replacement Cost", "Fuel Cost if Extend"],
orientation='h',
marker=dict(color=['#2ecc71', '#e74c3c']),
text=[f"USD {saving:,.2f}", f"USD {fuel_cost:,.2f}"],
textposition='auto'
))
fig2.update_layout(
title="Perbandingan Biaya",
title_font=dict(size=18, color="#f1c40f"),
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)',
font=dict(family="Poppins", size=12, color="#ecf0f1"),
showlegend=False,
xaxis=dict(showgrid=True, gridcolor='rgba(255,255,255,0.2)'),
yaxis=dict(showgrid=False)
)
st.plotly_chart(fig2, use_container_width=True)
st.subheader("🔄 Opsi Tindakan")
choice = st.radio("Pilih tindakan:", ["replacement/service", "extend component"], horizontal=True)
if choice == "replacement/service":
st.success("✅ Anda memilih untuk replacement component.")
else:
st.error("❌ Anda memilih untuk extend component.")
if st.button("Submit"):
st.session_state.submitted = True
st.rerun() # Mengganti st.experimental_rerun() dengan st.rerun()
st.markdown("---")
st.markdown("© 2025 Your Company. All Rights Reserved.
", unsafe_allow_html=True)