Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -288,7 +288,7 @@ body {
|
|
| 288 |
st.markdown(f"""
|
| 289 |
<div class="header-container">
|
| 290 |
<div class="header-title">
|
| 291 |
-
<h1>
|
| 292 |
<p>Proactive Safety Intelligence for Mining Operations</p>
|
| 293 |
</div>
|
| 294 |
<div class="header-logo">
|
|
@@ -1159,7 +1159,7 @@ import plotly.graph_objects as go
|
|
| 1159 |
|
| 1160 |
# =================== OBJECTIVE 5: Operator Fatigue Risk Gradient Dashboard =====================
|
| 1161 |
# ... (kode sebelumnya tetap sama) ...
|
| 1162 |
-
st.subheader("OBJECTIVE 5: See your team’s
|
| 1163 |
|
| 1164 |
# Custom CSS — tetap seperti sebelumnya (sudah sesuai preferensi)
|
| 1165 |
st.markdown("""
|
|
@@ -1558,7 +1558,7 @@ else:
|
|
| 1558 |
|
| 1559 |
st.markdown(f"""
|
| 1560 |
<div class="ai-insight-box">
|
| 1561 |
-
<div class="ai-insight-title">
|
| 1562 |
<ul style="padding-left: 20px; margin: 8px 0; line-height: 1.5;">
|
| 1563 |
<li>{ob_insights[0]}</li>
|
| 1564 |
<li>{ob_insights[1]}</li>
|
|
@@ -1591,7 +1591,7 @@ else:
|
|
| 1591 |
|
| 1592 |
st.markdown(f"""
|
| 1593 |
<div class="ai-insight-box">
|
| 1594 |
-
<div class="ai-insight-title">
|
| 1595 |
<ul style="padding-left: 20px; margin: 8px 0; line-height: 1.5;">
|
| 1596 |
<li>{coal_insights[0]}</li>
|
| 1597 |
<li>{coal_insights[1]}</li>
|
|
@@ -1603,82 +1603,111 @@ else:
|
|
| 1603 |
st.info("No HAULING COAL data for analysis.")
|
| 1604 |
|
| 1605 |
# ===============================================================
|
| 1606 |
-
# RECOMMENDATIONS —
|
| 1607 |
# ===============================================================
|
| 1608 |
col_rec1, col_rec2 = st.columns(2)
|
| 1609 |
|
| 1610 |
-
|
| 1611 |
-
rec = {}
|
| 1612 |
if not top_ob.empty:
|
| 1613 |
w = len(top_ob[top_ob['slope'] > 0])
|
| 1614 |
ot = len(top_ob[top_ob['slope'] == 0])
|
| 1615 |
avg = top_ob['weekly_avg'].mean()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1616 |
if w > 5:
|
| 1617 |
-
|
| 1618 |
-
|
| 1619 |
-
|
| 1620 |
-
|
| 1621 |
-
|
| 1622 |
-
elif avg > 8:
|
| 1623 |
-
r = "Review scheduling and rest protocols to reduce event frequency."
|
| 1624 |
-
reason = "Elevated average event rate increases cumulative fatigue exposure."
|
| 1625 |
else:
|
| 1626 |
-
|
| 1627 |
-
reason = "Risk profile is stable; focus on sustaining safe practices."
|
| 1628 |
-
rec['ob'] = r
|
| 1629 |
-
rec['ob_reason'] = reason
|
| 1630 |
|
| 1631 |
-
|
| 1632 |
-
|
| 1633 |
-
|
| 1634 |
-
avg = top_coal['weekly_avg'].mean()
|
| 1635 |
-
if w > 5:
|
| 1636 |
-
r = "Prioritize fatigue intervention for operators with worsening trends."
|
| 1637 |
-
reason = "High proportion of deteriorating operators signals emerging fatigue risks."
|
| 1638 |
-
elif ot > 4:
|
| 1639 |
-
r = "Validate data completeness — high One Time Event count may indicate reporting gaps."
|
| 1640 |
-
reason = "Operators with single-week data cannot yield reliable trend analysis."
|
| 1641 |
-
elif avg > 8:
|
| 1642 |
-
r = "Review scheduling and rest protocols to reduce event frequency."
|
| 1643 |
-
reason = "Elevated average event rate increases cumulative fatigue exposure."
|
| 1644 |
else:
|
| 1645 |
-
|
| 1646 |
-
reason = "Risk profile is stable; focus on sustaining safe practices."
|
| 1647 |
-
rec['coal'] = r
|
| 1648 |
-
rec['coal_reason'] = reason
|
| 1649 |
-
return rec
|
| 1650 |
|
| 1651 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1652 |
|
| 1653 |
-
with col_rec1:
|
| 1654 |
-
if 'ob' in ai_rec:
|
| 1655 |
st.markdown("### OB HAULER Recommendations")
|
| 1656 |
st.markdown(f"""
|
| 1657 |
<div class="recommendation-box">
|
| 1658 |
<div class="recommendation-title">Action Plan</div>
|
| 1659 |
-
<
|
| 1660 |
-
|
|
|
|
|
|
|
|
|
|
| 1661 |
</div>
|
| 1662 |
""", unsafe_allow_html=True)
|
| 1663 |
else:
|
| 1664 |
st.info("No OB HAULER recommendations.")
|
| 1665 |
|
| 1666 |
with col_rec2:
|
| 1667 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1668 |
st.markdown("### HAULING COAL Recommendations")
|
| 1669 |
st.markdown(f"""
|
| 1670 |
<div class="recommendation-box">
|
| 1671 |
<div class="recommendation-title">Action Plan</div>
|
| 1672 |
-
<
|
| 1673 |
-
|
|
|
|
|
|
|
|
|
|
| 1674 |
</div>
|
| 1675 |
""", unsafe_allow_html=True)
|
| 1676 |
else:
|
| 1677 |
st.info("No HAULING COAL recommendations.")
|
| 1678 |
-
|
| 1679 |
-
except Exception as e:
|
| 1680 |
-
st.error(f"Error in Top 10 Operator analysis: {str(e)}")
|
| 1681 |
-
st.exception(e)
|
| 1682 |
# =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
|
| 1683 |
st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
|
| 1684 |
|
|
|
|
| 288 |
st.markdown(f"""
|
| 289 |
<div class="header-container">
|
| 290 |
<div class="header-title">
|
| 291 |
+
<h1>Advanced Fatigue Analysis</h1>
|
| 292 |
<p>Proactive Safety Intelligence for Mining Operations</p>
|
| 293 |
</div>
|
| 294 |
<div class="header-logo">
|
|
|
|
| 1159 |
|
| 1160 |
# =================== OBJECTIVE 5: Operator Fatigue Risk Gradient Dashboard =====================
|
| 1161 |
# ... (kode sebelumnya tetap sama) ...
|
| 1162 |
+
st.subheader("OBJECTIVE 5: See your team’s Fatigue Hazard Profile!")
|
| 1163 |
|
| 1164 |
# Custom CSS — tetap seperti sebelumnya (sudah sesuai preferensi)
|
| 1165 |
st.markdown("""
|
|
|
|
| 1558 |
|
| 1559 |
st.markdown(f"""
|
| 1560 |
<div class="ai-insight-box">
|
| 1561 |
+
<div class="ai-insight-title">Hazard Summary</div>
|
| 1562 |
<ul style="padding-left: 20px; margin: 8px 0; line-height: 1.5;">
|
| 1563 |
<li>{ob_insights[0]}</li>
|
| 1564 |
<li>{ob_insights[1]}</li>
|
|
|
|
| 1591 |
|
| 1592 |
st.markdown(f"""
|
| 1593 |
<div class="ai-insight-box">
|
| 1594 |
+
<div class="ai-insight-title">Hazard Summary</div>
|
| 1595 |
<ul style="padding-left: 20px; margin: 8px 0; line-height: 1.5;">
|
| 1596 |
<li>{coal_insights[0]}</li>
|
| 1597 |
<li>{coal_insights[1]}</li>
|
|
|
|
| 1603 |
st.info("No HAULING COAL data for analysis.")
|
| 1604 |
|
| 1605 |
# ===============================================================
|
| 1606 |
+
# RECOMMENDATIONS — DIPERBARUI: 3 list per fleet, sesuai 3 poin Risk Summary
|
| 1607 |
# ===============================================================
|
| 1608 |
col_rec1, col_rec2 = st.columns(2)
|
| 1609 |
|
| 1610 |
+
with col_rec1:
|
|
|
|
| 1611 |
if not top_ob.empty:
|
| 1612 |
w = len(top_ob[top_ob['slope'] > 0])
|
| 1613 |
ot = len(top_ob[top_ob['slope'] == 0])
|
| 1614 |
avg = top_ob['weekly_avg'].mean()
|
| 1615 |
+
max_risk = top_ob['weekly_avg'].max()
|
| 1616 |
+
|
| 1617 |
+
# 3 rekomendasi, paralel dengan 3 poin Risk Summary
|
| 1618 |
+
rec_list = []
|
| 1619 |
+
|
| 1620 |
+
# 1. Trend-driven action
|
| 1621 |
if w > 5:
|
| 1622 |
+
rec_list.append("Conduct targeted fatigue risk assessments for operators with worsening trends (slope > 0).")
|
| 1623 |
+
elif w > 0 and w <= 5:
|
| 1624 |
+
rec_list.append("Monitor worsening-trend operators weekly and schedule supervisor check-ins.")
|
| 1625 |
+
elif w == 0 and len(top_ob[top_ob['slope'] < 0]) > 0:
|
| 1626 |
+
rec_list.append("Recognize improving operators — consider sharing best practices internally.")
|
|
|
|
|
|
|
|
|
|
| 1627 |
else:
|
| 1628 |
+
rec_list.append("Maintain current monitoring for stable trend profile.")
|
|
|
|
|
|
|
|
|
|
| 1629 |
|
| 1630 |
+
# 2. One-Time Event follow-up
|
| 1631 |
+
if ot > 0:
|
| 1632 |
+
rec_list.append(f"Re-engage {ot} <b>One Time Event</b> operators to verify data completeness and activity status.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1633 |
else:
|
| 1634 |
+
rec_list.append("Trend analysis is reliable — all operators have multi-week activity.")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1635 |
|
| 1636 |
+
# 3. Benchmark & sustain
|
| 1637 |
+
if avg > 8:
|
| 1638 |
+
rec_list.append("Initiate immediate review of shift scheduling and rest-break compliance.")
|
| 1639 |
+
elif avg > 5:
|
| 1640 |
+
rec_list.append("Conduct monthly fatigue KPI review using cohort average as baseline.")
|
| 1641 |
+
else:
|
| 1642 |
+
rec_list.append("Sustain current protocols — risk level is within acceptable range.")
|
| 1643 |
+
|
| 1644 |
+
# Ensure exactly 3 items
|
| 1645 |
+
while len(rec_list) < 3:
|
| 1646 |
+
rec_list.append("—")
|
| 1647 |
|
|
|
|
|
|
|
| 1648 |
st.markdown("### OB HAULER Recommendations")
|
| 1649 |
st.markdown(f"""
|
| 1650 |
<div class="recommendation-box">
|
| 1651 |
<div class="recommendation-title">Action Plan</div>
|
| 1652 |
+
<ul style="padding-left: 20px; margin: 8px 0; line-height: 1.5;">
|
| 1653 |
+
<li>{rec_list[0]}</li>
|
| 1654 |
+
<li>{rec_list[1]}</li>
|
| 1655 |
+
<li>{rec_list[2]}</li>
|
| 1656 |
+
</ul>
|
| 1657 |
</div>
|
| 1658 |
""", unsafe_allow_html=True)
|
| 1659 |
else:
|
| 1660 |
st.info("No OB HAULER recommendations.")
|
| 1661 |
|
| 1662 |
with col_rec2:
|
| 1663 |
+
if not top_coal.empty:
|
| 1664 |
+
w = len(top_coal[top_coal['slope'] > 0])
|
| 1665 |
+
ot = len(top_coal[top_coal['slope'] == 0])
|
| 1666 |
+
avg = top_coal['weekly_avg'].mean()
|
| 1667 |
+
max_risk = top_coal['weekly_avg'].max()
|
| 1668 |
+
|
| 1669 |
+
rec_list = []
|
| 1670 |
+
|
| 1671 |
+
# 1. Trend-driven action
|
| 1672 |
+
if w > 5:
|
| 1673 |
+
rec_list.append("Conduct targeted fatigue risk assessments for operators with worsening trends (slope > 0).")
|
| 1674 |
+
elif w > 0 and w <= 5:
|
| 1675 |
+
rec_list.append("Monitor worsening-trend operators weekly and schedule supervisor check-ins.")
|
| 1676 |
+
elif w == 0 and len(top_coal[top_coal['slope'] < 0]) > 0:
|
| 1677 |
+
rec_list.append("Recognize improving operators — consider sharing best practices internally.")
|
| 1678 |
+
else:
|
| 1679 |
+
rec_list.append("Maintain current monitoring for stable trend profile.")
|
| 1680 |
+
|
| 1681 |
+
# 2. One-Time Event follow-up
|
| 1682 |
+
if ot > 0:
|
| 1683 |
+
rec_list.append(f"Re-engage {ot} <b>One Time Event</b> operators to verify data completeness and activity status.")
|
| 1684 |
+
else:
|
| 1685 |
+
rec_list.append("Trend analysis is reliable — all operators have multi-week activity.")
|
| 1686 |
+
|
| 1687 |
+
# 3. Benchmark & sustain
|
| 1688 |
+
if avg > 8:
|
| 1689 |
+
rec_list.append("Initiate immediate review of shift scheduling and rest-break compliance.")
|
| 1690 |
+
elif avg > 5:
|
| 1691 |
+
rec_list.append("Conduct monthly fatigue KPI review using cohort average as baseline.")
|
| 1692 |
+
else:
|
| 1693 |
+
rec_list.append("Sustain current protocols — risk level is within acceptable range.")
|
| 1694 |
+
|
| 1695 |
+
while len(rec_list) < 3:
|
| 1696 |
+
rec_list.append("—")
|
| 1697 |
+
|
| 1698 |
st.markdown("### HAULING COAL Recommendations")
|
| 1699 |
st.markdown(f"""
|
| 1700 |
<div class="recommendation-box">
|
| 1701 |
<div class="recommendation-title">Action Plan</div>
|
| 1702 |
+
<ul style="padding-left: 20px; margin: 8px 0; line-height: 1.5;">
|
| 1703 |
+
<li>{rec_list[0]}</li>
|
| 1704 |
+
<li>{rec_list[1]}</li>
|
| 1705 |
+
<li>{rec_list[2]}</li>
|
| 1706 |
+
</ul>
|
| 1707 |
</div>
|
| 1708 |
""", unsafe_allow_html=True)
|
| 1709 |
else:
|
| 1710 |
st.info("No HAULING COAL recommendations.")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1711 |
# =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
|
| 1712 |
st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
|
| 1713 |
|