SHELLAPANDIANGANHUNGING commited on
Commit
1e96998
·
verified ·
1 Parent(s): bba4141

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -45
app.py CHANGED
@@ -1657,6 +1657,18 @@ else:
1657
  except Exception as e:
1658
  st.error(f"Error in Top 10 Operator analysis: {str(e)}")
1659
  st.exception(e) # optionally show full traceback during dev
 
 
 
 
 
 
 
 
 
 
 
 
1660
  # =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
1661
  st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
1662
 
@@ -1674,11 +1686,34 @@ with col_insights:
1674
 
1675
  st.markdown(f"**Critical Hour Risk (3-6 AM)**")
1676
  bg_color = "#ffcccc" if critical_pct > 50 else "#ffebcc" if critical_pct > 25 else "#ffffcc" if critical_pct > 10 else "#e6ffe6"
1677
- 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)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1678
  if critical_pct > 10:
1679
- 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.")
 
 
 
1680
  else:
1681
- st.info(f"{critical_pct:.1f}% of alerts occur during critical hours. This is within acceptable range.")
 
 
 
 
1682
 
1683
  # 2. High-Speed Fatigue Analysis (Environmental Risk)
1684
  if col_speed and col_speed in df.columns:
@@ -1687,69 +1722,107 @@ with col_insights:
1687
  high_speed_pct = (len(high_speed_fatigue) / len(df)) * 100 if len(df) > 0 else 0
1688
 
1689
  st.markdown(f"**High-Speed Fatigue Risk (Speed > {high_speed_threshold:.0f} km/h)**")
1690
- # Ganti st.metric dengan HTML custom
1691
- st.markdown(f"""
1692
- <div style="font-size: 24px; font-weight: bold;">{len(high_speed_fatigue)}</div>
1693
- <div style="color: red; font-size: 14px; margin-top: -5px;">↑ {high_speed_pct:.1f}% of total alerts</div>
1694
- """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
1695
  if high_speed_pct > 20:
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.")
 
 
 
1699
  else:
1700
  st.info("Speed data not available for High-Speed Fatigue Analysis.")
1701
- # 3.Objective
1702
- if col_shift and col_shift in df.columns:
1703
- shift_counts = df[col_shift].value_counts()
1704
 
 
 
 
1705
  st.markdown(f"**Shift Pattern Risk**")
 
1706
  for shift_val in shift_counts.index:
1707
  shift_pct = (shift_counts[shift_val] / len(df)) * 100
1708
- # Ganti st.metric dengan HTML custom
1709
- st.markdown(f"""<div style="font-size: 24px; font-weight: bold;">{shift_counts[shift_val]}</div><div style="color: red; font-size: 14px; margin-top: -5px;">↑ {shift_pct:.1f}% of total alerts</div>""", unsafe_allow_html=True)
1710
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1711
  if shift_pct > 50:
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}%).")
 
 
 
1715
  else:
1716
  st.info("Shift data not available for Shift Pattern Analysis.")
1717
 
1718
 
1719
  # 4. Operator Risk Profiling
1720
- # 4. Operator Risk Profiling
1721
- if col_operator and col_operator in df.columns:
1722
- operator_alerts = df[col_operator].value_counts()
1723
- top_risk_operators = operator_alerts.head(5) # Top 5 operators by alerts
1724
-
1725
- st.markdown("**High-Risk Operator Identification**")
1726
 
1727
- # Warna berdasarkan ranking 1–5
1728
- colors = ["#d32f2f", "#e57373", "#ef9a9a", "#ffcdd2", "#ffe1e4"]
1729
 
1730
- for idx, (op_name, count) in enumerate(top_risk_operators.items()):
1731
- op_pct = (count / len(df)) * 100
1732
- color = colors[idx] if idx < len(colors) else colors[-1]
1733
 
1734
- # Teks normal untuk nama dan jumlah alert
1735
- st.markdown(f"**Operator:** {op_name} \n**Alerts:** {count}")
 
1736
 
1737
- # Hanya 'Share' yang berwarna sesuai ranking
1738
- st.markdown(
1739
- f"<span style='font-weight:600'>Share:</span> "
1740
- f"<span style='color:{color}; font-weight:700'>{op_pct:.1f}% of total alerts</span>",
1741
- unsafe_allow_html=True
1742
- )
1743
 
1744
- # Risk message (tetap gunakan component Streamlit agar konsisten)
1745
- if op_pct > 5:
1746
- st.warning(f"Operator {op_name} has high fatigue risk ({op_pct:.1f}%). Consider coaching or rest plan.")
1747
- else:
1748
- st.info(f"Operator {op_name} fatigue risk is within acceptable range ({op_pct:.1f}%).")
 
1749
 
1750
- else:
1751
- st.info("Operator data not available for Operator Risk Profiling.")
 
 
 
1752
 
 
 
1753
 
1754
 
1755
  # Kolom kanan: AI Recommendations
@@ -1826,7 +1899,6 @@ with col_recs:
1826
  # Ambil data_point dan ganti teks persentase di dalamnya menjadi warna merah
1827
  data_point_text = rec['data_point']
1828
  # Ganti pola persentase (X.X%) dengan span warna merah
1829
- import re
1830
  # Cari pola seperti "1.6%", "21.2%", dll.
1831
  data_point_colored = re.sub(r'(\d+\.?\d*%)', r'<span style="color: red;">\1</span>', data_point_text)
1832
 
@@ -1875,4 +1947,4 @@ with col_recs:
1875
 
1876
  # ================= FOOTER ===========================
1877
  st.markdown("---")
1878
- st.markdown('<div class="footer">FatigueAnalyzer - Transforming Mining Safety with Intelligent Analytics | Contact: info@bukittechnology.com</div>', unsafe_allow_html=True)
 
1657
  except Exception as e:
1658
  st.error(f"Error in Top 10 Operator analysis: {str(e)}")
1659
  st.exception(e) # optionally show full traceback during dev
1660
+ Berikut adalah kode Objective 6 Anda yang telah diperbaiki. Kini, bagian **Critical Hour (1)**, **High-Speed Fatigue (2)**, dan **Shift Pattern (3)** menggunakan tampilan yang seragam: **jumlah alert dalam ukuran besar dan tebal, diikuti persentase dalam warna merah**. Warna latar belakang untuk bagian Shift Pattern (3) disamakan dengan bagian lainnya, dan warna teks persentase untuk Shift 1 dan 2 diatur menjadi merah.
1661
+
1662
+ Perubahan utama:
1663
+ 1. Ganti `st.metric` dan `st.markdown` yang sebelumnya tidak seragam.
1664
+ 2. Gunakan `st.markdown` dengan `unsafe_allow_html=True` untuk menampilkan jumlah dan persentase.
1665
+ 3. Terapkan `st.markdown` untuk `st.warning` dan `st.info` agar teks persentase berwarna merah.
1666
+ 4. Gunakan warna latar belakang yang konsisten untuk Shift Pattern (mengikuti pola Critical Hour).
1667
+ 5. Tambahkan `import re` di awal file jika belum ada.
1668
+
1669
+
1670
+ import re # Tambahkan ini jika belum ada
1671
+
1672
  # =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
1673
  st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
1674
 
 
1686
 
1687
  st.markdown(f"**Critical Hour Risk (3-6 AM)**")
1688
  bg_color = "#ffcccc" if critical_pct > 50 else "#ffebcc" if critical_pct > 25 else "#ffffcc" if critical_pct > 10 else "#e6ffe6"
1689
+
1690
+ # Tampilkan jumlah dan persentase dalam satu div
1691
+ st.markdown(
1692
+ f"""
1693
+ <div style="background-color: {bg_color}; padding: 10px; border-radius: 8px; margin-bottom: 10px;">
1694
+ <div style="font-size: 24px; font-weight: bold; color: #000000;">
1695
+ {len(critical_alerts)}
1696
+ </div>
1697
+ <div style="color: #d32f2f; font-size: 16px; font-weight: bold; margin-top: -10px;">
1698
+ ↑ {critical_pct:.1f}% of total alerts
1699
+ </div>
1700
+ </div>
1701
+ """,
1702
+ unsafe_allow_html=True
1703
+ )
1704
+
1705
+ # Gunakan st.markdown untuk warning/info dengan persentase berwarna merah tebal
1706
  if critical_pct > 10:
1707
+ st.markdown(
1708
+ f"<span style='color:#d32f2f; font-weight:bold;'>⚠️ High risk: {critical_pct:.1f}% of fatigue alerts occur during critical hours (3-6 AM). This is a known circadian dip period.</span>",
1709
+ unsafe_allow_html=True
1710
+ )
1711
  else:
1712
+ st.markdown(
1713
+ f"<span style='color:#d32f2f; font-weight:bold;'>✅ {critical_pct:.1f}% of alerts occur during critical hours. This is within acceptable range.</span>",
1714
+ unsafe_allow_html=True
1715
+ )
1716
+
1717
 
1718
  # 2. High-Speed Fatigue Analysis (Environmental Risk)
1719
  if col_speed and col_speed in df.columns:
 
1722
  high_speed_pct = (len(high_speed_fatigue) / len(df)) * 100 if len(df) > 0 else 0
1723
 
1724
  st.markdown(f"**High-Speed Fatigue Risk (Speed > {high_speed_threshold:.0f} km/h)**")
1725
+
1726
+ # Tampilkan jumlah dan persentase dalam satu div
1727
+ st.markdown(
1728
+ f"""
1729
+ <div style="background-color: #f0f8ff; padding: 10px; border-radius: 8px; margin-bottom: 10px; border-left: 5px solid #007BFF;">
1730
+ <div style="font-size: 24px; font-weight: bold; color: #000000;">
1731
+ {len(high_speed_fatigue)}
1732
+ </div>
1733
+ <div style="color: #d32f2f; font-size: 16px; font-weight: bold; margin-top: -10px;">
1734
+ ↑ {high_speed_pct:.1f}% of total alerts
1735
+ </div>
1736
+ </div>
1737
+ """,
1738
+ unsafe_allow_html=True
1739
+ )
1740
+
1741
+ # Gunakan st.markdown untuk warning/info dengan persentase berwarna merah tebal
1742
  if high_speed_pct > 20:
1743
+ st.markdown(
1744
+ f"<span style='color:#d32f2f; font-weight:bold;'>⚠️ High risk: {high_speed_pct:.1f}% of fatigue alerts occur at high speeds. This increases accident severity potential.</span>",
1745
+ unsafe_allow_html=True
1746
+ )
1747
  else:
1748
+ st.markdown(
1749
+ f"<span style='color:#d32f2f; font-weight:bold;'>✅ {high_speed_pct:.1f}% of alerts occur at high speeds. This is within acceptable range.</span>",
1750
+ unsafe_allow_html=True
1751
+ )
1752
  else:
1753
  st.info("Speed data not available for High-Speed Fatigue Analysis.")
 
 
 
1754
 
1755
+ # 3. Shift Pattern Analysis
1756
+ if col_shift and col_shift in df.columns:
1757
+ shift_counts = df[col_shift].value_counts()
1758
  st.markdown(f"**Shift Pattern Risk**")
1759
+
1760
  for shift_val in shift_counts.index:
1761
  shift_pct = (shift_counts[shift_val] / len(df)) * 100
 
 
1762
 
1763
+ # Tampilkan jumlah dan persentase dalam satu div dengan warna latar belakang seragam
1764
+ st.markdown(
1765
+ f"""
1766
+ <div style="background-color: #f0f8ff; padding: 10px; border-radius: 8px; margin-bottom: 10px; border-left: 5px solid #007BFF;">
1767
+ <div style="font-size: 24px; font-weight: bold; color: #000000;">Shift {shift_val}</div>
1768
+ <div style="font-size: 28px; font-weight: bold; color: #000000; margin: 10px 0;">
1769
+ {shift_counts[shift_val]}
1770
+ </div>
1771
+ <div style="color: #d32f2f; font-size: 16px; font-weight: bold; margin-top: -10px;">
1772
+ ↑ {shift_pct:.1f}% of total alerts
1773
+ </div>
1774
+ </div>
1775
+ """,
1776
+ unsafe_allow_html=True
1777
+ )
1778
+
1779
+ # Gunakan st.markdown untuk warning/info dengan persentase berwarna merah tebal
1780
  if shift_pct > 50:
1781
+ st.markdown(
1782
+ f"<span style='color:#d32f2f; font-weight:bold;'>⚠️ Shift {shift_val} has disproportionately high alerts ({shift_pct:.1f}%). Review shift scheduling and workload.</span>",
1783
+ unsafe_allow_html=True
1784
+ )
1785
  else:
1786
+ st.markdown(
1787
+ f"<span style='color:#d32f2f; font-weight:bold;'>✅ Shift {shift_val} alert distribution is acceptable ({shift_pct:.1f}%).</span>",
1788
+ unsafe_allow_html=True
1789
+ )
1790
  else:
1791
  st.info("Shift data not available for Shift Pattern Analysis.")
1792
 
1793
 
1794
  # 4. Operator Risk Profiling
1795
+ if col_operator and col_operator in df.columns:
1796
+ operator_alerts = df[col_operator].value_counts()
1797
+ top_risk_operators = operator_alerts.head(5) # Top 5 operators by alerts
 
 
 
1798
 
1799
+ st.markdown("**High-Risk Operator Identification**")
 
1800
 
1801
+ # Warna berdasarkan ranking 1–5
1802
+ colors = ["#d32f2f", "#e57373", "#ef9a9a", "#ffcdd2", "#ffe1e4"]
 
1803
 
1804
+ for idx, (op_name, count) in enumerate(top_risk_operators.items()):
1805
+ op_pct = (count / len(df)) * 100
1806
+ color = colors[idx] if idx < len(colors) else colors[-1]
1807
 
1808
+ # Teks normal untuk nama dan jumlah alert
1809
+ st.markdown(f"**Operator:** {op_name} \n**Alerts:** {count}")
 
 
 
 
1810
 
1811
+ # Hanya 'Share' yang berwarna sesuai ranking
1812
+ st.markdown(
1813
+ f"<span style='font-weight:600'>Share:</span> "
1814
+ f"<span style='color:{color}; font-weight:700'>{op_pct:.1f}% of total alerts</span>",
1815
+ unsafe_allow_html=True
1816
+ )
1817
 
1818
+ # Risk message (tetap gunakan component Streamlit agar konsisten)
1819
+ if op_pct > 5:
1820
+ st.warning(f"Operator {op_name} has high fatigue risk ({op_pct:.1f}%). Consider coaching or rest plan.")
1821
+ else:
1822
+ st.info(f"Operator {op_name} fatigue risk is within acceptable range ({op_pct:.1f}%).")
1823
 
1824
+ else:
1825
+ st.info("Operator data not available for Operator Risk Profiling.")
1826
 
1827
 
1828
  # Kolom kanan: AI Recommendations
 
1899
  # Ambil data_point dan ganti teks persentase di dalamnya menjadi warna merah
1900
  data_point_text = rec['data_point']
1901
  # Ganti pola persentase (X.X%) dengan span warna merah
 
1902
  # Cari pola seperti "1.6%", "21.2%", dll.
1903
  data_point_colored = re.sub(r'(\d+\.?\d*%)', r'<span style="color: red;">\1</span>', data_point_text)
1904
 
 
1947
 
1948
  # ================= FOOTER ===========================
1949
  st.markdown("---")
1950
+ st.markdown('<div class="footer">FatigueAnalyzer - Transforming Mining Safety with Intelligent Analytics | Contact: info@bukittechnology.com</div>', unsafe_allow_html=True)