SHELLAPANDIANGANHUNGING commited on
Commit
39470a2
·
verified ·
1 Parent(s): 83e00e2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -19
app.py CHANGED
@@ -1676,23 +1676,26 @@ with col_insights:
1676
  critical_pct = (len(critical_alerts) / len(df)) * 100 if len(df) > 0 else 0
1677
 
1678
  st.markdown(f"**Critical Hour Risk (3-6 AM)**")
1679
- # Use conditional formatting for background color
1680
  bg_color = "#ffcccc" if critical_pct > 50 else "#ffebcc" if critical_pct > 25 else "#ffffcc" if critical_pct > 10 else "#e6ffe6"
1681
  st.markdown(f'<div style="background-color: {bg_color}; padding: 10px; border-radius: 5px;">Critical Hour Alerts: {len(critical_alerts)} ({critical_pct:.1f}% of total alerts)</div>', unsafe_allow_html=True)
1682
- if critical_pct > 10: # If more than 10% of alerts happen in critical hours
1683
  st.warning(f"High risk: {critical_pct:.1f}% of fatigue alerts occur during critical hours (3-6 AM). This is a known circadian dip period.")
1684
  else:
1685
  st.info(f"{critical_pct:.1f}% of alerts occur during critical hours. This is within acceptable range.")
1686
 
1687
  # 2. High-Speed Fatigue Analysis (Environmental Risk)
1688
  if col_speed and col_speed in df.columns:
1689
- high_speed_threshold = df[col_speed].quantile(0.75) if not df[col_speed].dropna().empty else 0 # Handle empty series
1690
  high_speed_fatigue = df[df[col_speed] >= high_speed_threshold] if high_speed_threshold > 0 else pd.DataFrame()
1691
  high_speed_pct = (len(high_speed_fatigue) / len(df)) * 100 if len(df) > 0 else 0
1692
 
1693
  st.markdown(f"**High-Speed Fatigue Risk (Speed > {high_speed_threshold:.0f} km/h)**")
1694
- st.metric("High-Speed Fatigue Events", f"{len(high_speed_fatigue)}", f"{high_speed_pct:.1f}% of total alerts")
1695
- if high_speed_pct > 20: # If more than 20% of alerts happen at high speed
 
 
 
 
1696
  st.warning(f"High risk: {high_speed_pct:.1f}% of fatigue alerts occur at high speeds. This increases accident severity potential.")
1697
  else:
1698
  st.info(f"{high_speed_pct:.1f}% of alerts occur at high speeds. This is within acceptable range.")
@@ -1702,13 +1705,16 @@ with col_insights:
1702
  # 3. Shift Pattern Analysis
1703
  if col_shift and col_shift in df.columns:
1704
  shift_counts = df[col_shift].value_counts()
1705
- # shift_alerts_by_hour = df.groupby([col_shift, 'hour']).size().reset_index(name='alerts') # Tidak digunakan dalam tampilan ini
1706
-
1707
  st.markdown(f"**Shift Pattern Risk**")
1708
  for shift_val in shift_counts.index:
1709
  shift_pct = (shift_counts[shift_val] / len(df)) * 100
1710
- st.metric(f"Shift {shift_val} Alerts", f"{shift_counts[shift_val]}", f"{shift_pct:.1f}% of total alerts")
1711
- if shift_pct > 50: # If one shift has more than 50% of alerts
 
 
 
 
1712
  st.warning(f"Shift {shift_val} has disproportionately high alerts ({shift_pct:.1f}%). Review shift scheduling and workload.")
1713
  else:
1714
  st.info(f"Shift {shift_val} alert distribution is acceptable ({shift_pct:.1f}%).")
@@ -1718,13 +1724,17 @@ with col_insights:
1718
  # 4. Operator Risk Profiling
1719
  if col_operator and col_operator in df.columns:
1720
  operator_alerts = df[col_operator].value_counts()
1721
- top_risk_operators = operator_alerts.head(5) # Top 5 operators by alerts
1722
-
1723
  st.markdown(f"**High-Risk Operator Identification**")
1724
  for op_name, count in top_risk_operators.items():
1725
  op_pct = (count / len(df)) * 100
1726
- st.metric(f"Operator: {op_name}", f"{count} alerts", f"{op_pct:.1f}% of total alerts")
1727
- if op_pct > 5: # If an operator has more than 5% of all alerts
 
 
 
 
1728
  st.warning(f"Operator {op_name} has high fatigue risk ({op_pct:.1f}% of alerts). Consider coaching or rest plan.")
1729
  else:
1730
  st.info(f"Operator {op_name} fatigue risk is within acceptable range ({op_pct:.1f}%).")
@@ -1736,7 +1746,7 @@ with col_insights:
1736
  with col_recs:
1737
  st.subheader("Recommendations")
1738
  ai_recs = []
1739
- insights_found = [] # Untuk menyimpan insight yang ditemukan
1740
 
1741
  # Peak hour
1742
  if "hour" in df.columns and not df.empty:
@@ -1765,7 +1775,6 @@ with col_recs:
1765
 
1766
  # Generate recommendations based on found insights
1767
  if insights_found:
1768
- # Contoh rekomendasi berdasarkan insight
1769
  if any("circadian low" in i.lower() for i in insights_found):
1770
  ai_recs.append({
1771
  "recommendation": "Deploy enhanced fatigue monitoring systems (e.g., EOR) specifically during 3-6 AM shifts.",
@@ -1803,10 +1812,7 @@ with col_recs:
1803
  "reason": "No specific high-impact insights were automatically identified from the aggregated data in this section."
1804
  })
1805
 
1806
- # Menampilkan rekomendasi dalam format kotak yang sesuai dengan permintaan
1807
  for rec in ai_recs:
1808
- # Gunakan div dengan class khusus untuk membuat kotak rekomendasi di kolom kanan
1809
- # Gaya diambil dari .insight-box untuk konsistensi dan menghindari warna ungu
1810
  st.markdown(f"""
1811
  <div style="
1812
  background: #f8f9fa;
@@ -1847,4 +1853,4 @@ with col_recs:
1847
 
1848
  # ================= FOOTER ===========================
1849
  st.markdown("---")
1850
- st.markdown('<div class="footer">FatigueAnalyzer - Transforming Mining Safety with Intelligent Analytics | Contact: info@bukittechnology.com</div>', unsafe_allow_html=True)
 
1676
  critical_pct = (len(critical_alerts) / len(df)) * 100 if len(df) > 0 else 0
1677
 
1678
  st.markdown(f"**Critical Hour Risk (3-6 AM)**")
 
1679
  bg_color = "#ffcccc" if critical_pct > 50 else "#ffebcc" if critical_pct > 25 else "#ffffcc" if critical_pct > 10 else "#e6ffe6"
1680
  st.markdown(f'<div style="background-color: {bg_color}; padding: 10px; border-radius: 5px;">Critical Hour Alerts: {len(critical_alerts)} ({critical_pct:.1f}% of total alerts)</div>', unsafe_allow_html=True)
1681
+ if critical_pct > 10:
1682
  st.warning(f"High risk: {critical_pct:.1f}% of fatigue alerts occur during critical hours (3-6 AM). This is a known circadian dip period.")
1683
  else:
1684
  st.info(f"{critical_pct:.1f}% of alerts occur during critical hours. This is within acceptable range.")
1685
 
1686
  # 2. High-Speed Fatigue Analysis (Environmental Risk)
1687
  if col_speed and col_speed in df.columns:
1688
+ high_speed_threshold = df[col_speed].quantile(0.75) if not df[col_speed].dropna().empty else 0
1689
  high_speed_fatigue = df[df[col_speed] >= high_speed_threshold] if high_speed_threshold > 0 else pd.DataFrame()
1690
  high_speed_pct = (len(high_speed_fatigue) / len(df)) * 100 if len(df) > 0 else 0
1691
 
1692
  st.markdown(f"**High-Speed Fatigue Risk (Speed > {high_speed_threshold:.0f} km/h)**")
1693
+ # Ganti st.metric dengan HTML custom
1694
+ st.markdown(f"""
1695
+ <div style="font-size: 24px; font-weight: bold;">{len(high_speed_fatigue)}</div>
1696
+ <div style="color: red; font-size: 14px; margin-top: -5px;">↑ {high_speed_pct:.1f}% of total alerts</div>
1697
+ """, unsafe_allow_html=True)
1698
+ if high_speed_pct > 20:
1699
  st.warning(f"High risk: {high_speed_pct:.1f}% of fatigue alerts occur at high speeds. This increases accident severity potential.")
1700
  else:
1701
  st.info(f"{high_speed_pct:.1f}% of alerts occur at high speeds. This is within acceptable range.")
 
1705
  # 3. Shift Pattern Analysis
1706
  if col_shift and col_shift in df.columns:
1707
  shift_counts = df[col_shift].value_counts()
1708
+
 
1709
  st.markdown(f"**Shift Pattern Risk**")
1710
  for shift_val in shift_counts.index:
1711
  shift_pct = (shift_counts[shift_val] / len(df)) * 100
1712
+ # Ganti st.metric dengan HTML custom
1713
+ st.markdown(f"""
1714
+ <div style="font-size: 24px; font-weight: bold;">{shift_counts[shift_val]}</div>
1715
+ <div style="color: red; font-size: 14px; margin-top: -5px;">↑ {shift_pct:.1f}% of total alerts</div>
1716
+ """, unsafe_allow_html=True)
1717
+ if shift_pct > 50:
1718
  st.warning(f"Shift {shift_val} has disproportionately high alerts ({shift_pct:.1f}%). Review shift scheduling and workload.")
1719
  else:
1720
  st.info(f"Shift {shift_val} alert distribution is acceptable ({shift_pct:.1f}%).")
 
1724
  # 4. Operator Risk Profiling
1725
  if col_operator and col_operator in df.columns:
1726
  operator_alerts = df[col_operator].value_counts()
1727
+ top_risk_operators = operator_alerts.head(5)
1728
+
1729
  st.markdown(f"**High-Risk Operator Identification**")
1730
  for op_name, count in top_risk_operators.items():
1731
  op_pct = (count / len(df)) * 100
1732
+ # Ganti st.metric dengan HTML custom
1733
+ st.markdown(f"""
1734
+ <div style="font-size: 24px; font-weight: bold;">{count} alerts</div>
1735
+ <div style="color: red; font-size: 14px; margin-top: -5px;">↑ {op_pct:.1f}% of total alerts</div>
1736
+ """, unsafe_allow_html=True)
1737
+ if op_pct > 5:
1738
  st.warning(f"Operator {op_name} has high fatigue risk ({op_pct:.1f}% of alerts). Consider coaching or rest plan.")
1739
  else:
1740
  st.info(f"Operator {op_name} fatigue risk is within acceptable range ({op_pct:.1f}%).")
 
1746
  with col_recs:
1747
  st.subheader("Recommendations")
1748
  ai_recs = []
1749
+ insights_found = []
1750
 
1751
  # Peak hour
1752
  if "hour" in df.columns and not df.empty:
 
1775
 
1776
  # Generate recommendations based on found insights
1777
  if insights_found:
 
1778
  if any("circadian low" in i.lower() for i in insights_found):
1779
  ai_recs.append({
1780
  "recommendation": "Deploy enhanced fatigue monitoring systems (e.g., EOR) specifically during 3-6 AM shifts.",
 
1812
  "reason": "No specific high-impact insights were automatically identified from the aggregated data in this section."
1813
  })
1814
 
 
1815
  for rec in ai_recs:
 
 
1816
  st.markdown(f"""
1817
  <div style="
1818
  background: #f8f9fa;
 
1853
 
1854
  # ================= FOOTER ===========================
1855
  st.markdown("---")
1856
+ st.markdown('<div class="footer">FatigueAnalyzer - Transforming Mining Safety with Intelligent Analytics | Contact: info@bukittechnology.com</div>', unsafe_allow_html=True)