SHELLAPANDIANGANHUNGING commited on
Commit
8b6885c
·
verified ·
1 Parent(s): 88d651a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +279 -1
app.py CHANGED
@@ -1724,6 +1724,283 @@ else:
1724
  st.error(f"Error in Top 10 Operator analysis: {str(e)}")
1725
  st.exception(e)
1726
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1727
  # =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
1728
  st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
1729
 
@@ -2001,4 +2278,5 @@ st.markdown("---")
2001
  st.markdown(
2002
  '<div class="footer">FatigueAnalyzer - Transforming Mining Safety with Intelligent Analytics | Contact: info@bukittechnology.com</div>',
2003
  unsafe_allow_html=True
2004
- )
 
 
1724
  st.error(f"Error in Top 10 Operator analysis: {str(e)}")
1725
  st.exception(e)
1726
 
1727
+ # # =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
1728
+ # st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
1729
+
1730
+ # # Membagi tampilan menjadi dua kolom
1731
+ # col_insights, col_recs = st.columns(2)
1732
+
1733
+ # # =====================================================================
1734
+ # # 🔹 KOLOM KIRI — INSIGHTS BY ADVANCED ANALYTICS
1735
+ # # =====================================================================
1736
+ # with col_insights:
1737
+ # st.subheader("Insights by Advanced Analytics")
1738
+
1739
+ # # ===================== 1. Critical Hour Analysis =====================
1740
+ # critical_hours = [2, 3, 4, 5]
1741
+ # critical_alerts = df[df['hour'].isin(critical_hours)]
1742
+ # critical_pct = (len(critical_alerts) / len(df)) * 100 if len(df) > 0 else 0
1743
+
1744
+ # st.markdown(f"**Critical Hour Risk (3-6 AM)**")
1745
+ # bg_color = (
1746
+ # "#ffcccc" if critical_pct > 50 else
1747
+ # "#ffebcc" if critical_pct > 25 else
1748
+ # "#ffffcc" if critical_pct > 10 else
1749
+ # "#e6ffe6"
1750
+ # )
1751
+ # st.markdown(
1752
+ # f'<div style="background-color: {bg_color}; padding: 10px; border-radius: 5px;">'
1753
+ # f'Critical Hour Alerts: {len(critical_alerts)} ({critical_pct:.1f}% of total alerts)</div>',
1754
+ # unsafe_allow_html=True
1755
+ # )
1756
+
1757
+ # if critical_pct > 10:
1758
+ # st.warning(
1759
+ # f"High risk: {critical_pct:.1f}% of fatigue alerts occur during critical hours (3-6 AM). "
1760
+ # f"This is a known circadian dip period."
1761
+ # )
1762
+ # else:
1763
+ # st.info(
1764
+ # f"{critical_pct:.1f}% of alerts occur during critical hours. This is within acceptable range."
1765
+ # )
1766
+
1767
+ # # ===================== 2. High-Speed Fatigue Analysis =====================
1768
+ # if col_speed and col_speed in df.columns:
1769
+ # high_speed_threshold = 20
1770
+ # high_speed_fatigue = df[df[col_speed] >= high_speed_threshold]
1771
+ # high_speed_pct = (len(high_speed_fatigue) / len(df)) * 100 if len(df) > 0 else 0
1772
+
1773
+ # st.markdown(f"**High-Speed Fatigue Risk (Speed > {high_speed_threshold} km/h)**")
1774
+ # st.markdown(
1775
+ # f"""
1776
+ # <div style="font-size: 24px; font-weight: bold;">{len(high_speed_fatigue)}</div>
1777
+ # <div style="color: red; font-size: 14px; margin-top: -5px;">↑ {high_speed_pct:.1f}% of total alerts</div>
1778
+ # """,
1779
+ # unsafe_allow_html=True
1780
+ # )
1781
+
1782
+ # if high_speed_pct > 20:
1783
+ # st.warning(
1784
+ # f"High risk: {high_speed_pct:.1f}% of fatigue alerts occur at high speeds. "
1785
+ # f"This increases accident severity potential."
1786
+ # )
1787
+ # else:
1788
+ # st.info(
1789
+ # f"{high_speed_pct:.1f}% of alerts occur at high speeds. This is within acceptable range."
1790
+ # )
1791
+ # else:
1792
+ # st.info("Speed data not available for High-Speed Fatigue Analysis.")
1793
+
1794
+ # # ===================== 3. Shift Pattern Analysis =====================
1795
+ # if col_shift and col_shift in df.columns:
1796
+ # shift_counts = df[col_shift].value_counts()
1797
+ # st.markdown(f"**Shift Pattern Risk**")
1798
+
1799
+ # for shift_val in shift_counts.index:
1800
+ # shift_pct = (shift_counts[shift_val] / len(df)) * 100
1801
+
1802
+ # st.markdown(
1803
+ # f"""
1804
+ # <div style="font-size: 24px; font-weight: bold;">{shift_counts[shift_val]}</div>
1805
+ # <div style="color: red; font-size: 14px; margin-top: -5px;">↑ {shift_pct:.1f}% of total alerts</div>
1806
+ # """,
1807
+ # unsafe_allow_html=True
1808
+ # )
1809
+
1810
+ # if shift_pct > 50:
1811
+ # st.warning(
1812
+ # f"Shift {shift_val} has disproportionately high alerts ({shift_pct:.1f}%). "
1813
+ # f"Review shift scheduling and workload."
1814
+ # )
1815
+ # else:
1816
+ # st.info(
1817
+ # f"Shift {shift_val} alert distribution is acceptable ({shift_pct:.1f}%)."
1818
+ # )
1819
+ # else:
1820
+ # st.info("Shift data not available for Shift Pattern Analysis.")
1821
+
1822
+ # # ===================== 4. Operator Risk Profiling =====================
1823
+ # if col_operator and col_operator in df.columns:
1824
+ # operator_alerts = df[col_operator].value_counts()
1825
+ # top_risk_operators = operator_alerts.head(5)
1826
+
1827
+ # st.markdown("**High-Risk Operator Identification**")
1828
+ # colors = ["#d32f2f", "#e57373", "#ef9a9a", "#ffcdd2", "#ffe1e4"]
1829
+
1830
+ # for idx, (op_name, count) in enumerate(top_risk_operators.items()):
1831
+ # op_pct = (count / len(df)) * 100
1832
+ # color = colors[idx] if idx < len(colors) else colors[-1]
1833
+
1834
+ # st.markdown(
1835
+ # f"**Operator:** {op_name} \n**Alerts:** {count}"
1836
+ # )
1837
+ # st.markdown(
1838
+ # f"<span style='font-weight:600'>Share:</span> "
1839
+ # f"<span style='color:{color}; font-weight:700'>{op_pct:.1f}% of total alerts</span>",
1840
+ # unsafe_allow_html=True
1841
+ # )
1842
+
1843
+ # if op_pct > 5:
1844
+ # st.warning(
1845
+ # f"Operator {op_name} has high fatigue risk ({op_pct:.1f}%). "
1846
+ # f"Consider coaching or rest plan."
1847
+ # )
1848
+ # else:
1849
+ # st.info(
1850
+ # f"Operator {op_name} fatigue risk is within acceptable range ({op_pct:.1f}%)."
1851
+ # )
1852
+ # else:
1853
+ # st.info("Operator data not available for Operator Risk Profiling.")
1854
+
1855
+ # # =====================================================================
1856
+ # # 🔹 KOLOM KANAN — AI RECOMMENDATIONS (PER INSIGHT)
1857
+ # # =====================================================================
1858
+ # with col_recs:
1859
+ # st.subheader("Recommendations")
1860
+
1861
+ # # Reset list to collect recommendations per insight
1862
+ # ai_recommendations = []
1863
+
1864
+ # # 1. Critical Hour Insight → AI Rec
1865
+ # if "hour" in df.columns and not df.empty:
1866
+ # peak_hour = df["hour"].value_counts().idxmax()
1867
+ # critical_hours = [2, 3, 4, 5]
1868
+
1869
+ # if peak_hour in critical_hours:
1870
+ # ai_recommendations.append({
1871
+ # "action": "Deploy enhanced fatigue monitoring systems during 3-6 AM.",
1872
+ # "data_point": f"Critical Hour Alerts: {len(critical_alerts)} ({critical_pct:.1f}%)",
1873
+ # "reasoning": "High percentage of alerts during circadian low period."
1874
+ # })
1875
+ # else:
1876
+ # ai_recommendations.append({
1877
+ # "action": "Monitor fatigue patterns around peak hour (Hour {peak_hour}).",
1878
+ # "data_point": f"Peak Hour: {peak_hour}:00 — {df['hour'].value_counts()[peak_hour]} alerts",
1879
+ # "reasoning": "This hour shows highest fatigue occurrence."
1880
+ # })
1881
+
1882
+ # # 2. High-Speed Insight → AI Rec
1883
+ # if col_speed and col_speed in df.columns and not df.empty:
1884
+ # high_speed_threshold = 20
1885
+ # high_speed_fatigue = df[df[col_speed] >= high_speed_threshold]
1886
+ # high_speed_pct = (len(high_speed_fatigue) / len(df)) * 100 if len(df) > 0 else 0
1887
+
1888
+ # if high_speed_pct > 20:
1889
+ # ai_recommendations.append({
1890
+ # "action": "Implement speed-reduction protocols during fatigue-prone hours.",
1891
+ # "data_point": f"High-Speed Alerts: {len(high_speed_fatigue)} ({high_speed_pct:.1f}%)",
1892
+ # "reasoning": "High-speed alerts increase accident severity potential."
1893
+ # })
1894
+ # else:
1895
+ # ai_recommendations.append({
1896
+ # "action": "Maintain current speed monitoring — risk level is acceptable.",
1897
+ # "data_point": f"High-Speed Alerts: {len(high_speed_fatigue)} ({high_speed_pct:.1f}%)",
1898
+ # "reasoning": "Current high-speed fatigue rate is within acceptable range."
1899
+ # })
1900
+
1901
+ # # 3. Shift Pattern Insight → AI Rec
1902
+ # if col_shift and col_shift in df.columns and not df.empty:
1903
+ # worst_shift = df[col_shift].value_counts().idxmax()
1904
+ # shift_pct = (df[col_shift].value_counts()[worst_shift] / len(df)) * 100
1905
+
1906
+ # if shift_pct > 50:
1907
+ # ai_recommendations.append({
1908
+ # "action": "Review shift rotation schedules for Shift {worst_shift}.",
1909
+ # "data_point": f"Shift {worst_shift}: {df[col_shift].value_counts()[worst_shift]} alerts ({shift_pct:.1f}%)",
1910
+ # "reasoning": "Disproportionately high fatigue alerts indicate scheduling imbalance."
1911
+ # })
1912
+ # else:
1913
+ # ai_recommendations.append({
1914
+ # "action": "Continue monitoring all shifts — no dominant risk identified.",
1915
+ # "data_point": f"Shift {worst_shift}: {df[col_shift].value_counts()[worst_shift]} alerts ({shift_pct:.1f}%)",
1916
+ # "reasoning": "Shift distribution is balanced."
1917
+ # })
1918
+
1919
+ # # 4. Operator Risk Insight → AI Rec
1920
+ # if col_operator and col_operator in df.columns and not df.empty:
1921
+ # worst_operator = df[col_operator].value_counts().idxmax()
1922
+ # op_pct = (df[col_operator].value_counts()[worst_operator] / len(df)) * 100
1923
+
1924
+ # if op_pct > 5:
1925
+ # ai_recommendations.append({
1926
+ # "action": "Coaching or mandatory rest for the identified high-risk operator.",
1927
+ # "data_point": f"Operator {worst_operator}: {df[col_operator].value_counts()[worst_operator]} alerts ({op_pct:.1f}%)",
1928
+ # "reasoning": "Operator has highest fatigue alerts — requires individual intervention."
1929
+ # })
1930
+ # else:
1931
+ # ai_recommendations.append({
1932
+ # "action": "Continue general monitoring — no single operator dominates risk.",
1933
+ # "data_point": f"Top Operator: {worst_operator} — {df[col_operator].value_counts()[worst_operator]} alerts ({op_pct:.1f}%)",
1934
+ # "reasoning": "Risk is distributed across operators — no urgent individual action needed."
1935
+ # })
1936
+
1937
+ # # Render each recommendation as a card
1938
+ # for rec in ai_recommendations:
1939
+ # # Highlight percentages in red
1940
+ # data_point_colored = rec['data_point'].replace(
1941
+ # f"({rec['data_point'].split('(')[-1]}",
1942
+ # f"(<span style='color: red;'>{rec['data_point'].split('(')[-1]}"
1943
+ # ).replace(")", "</span>)")
1944
+
1945
+ # reasoning_colored = rec['reasoning'].replace(
1946
+ # f"({rec['reasoning'].split('(')[-1]}",
1947
+ # f"(<span style='color: red;'>{rec['reasoning'].split('(')[-1]}"
1948
+ # ).replace(")", "</span>)")
1949
+
1950
+ # st.markdown(
1951
+ # f"""
1952
+ # <div style="
1953
+ # background: #f8f9fa;
1954
+ # border: 1px solid #dee2e6;
1955
+ # border-radius: 8px;
1956
+ # padding: 15px;
1957
+ # margin: 10px 0;
1958
+ # box-shadow: 0 2px 8px rgba(0,0,0,0.05);
1959
+ # ">
1960
+ # <div style="
1961
+ # font-weight: bold;
1962
+ # background: #e9ecef;
1963
+ # padding: 8px;
1964
+ # border-radius: 5px;
1965
+ # margin-bottom: 8px;
1966
+ # border-left: 4px solid #495057;
1967
+ # ">
1968
+ # AI Recommendation
1969
+ # </div>
1970
+ # <div style="padding: 8px 0;">
1971
+ # <strong>Action:</strong> {rec['action']}
1972
+ # </div>
1973
+ # <div style="
1974
+ # padding: 8px;
1975
+ # background: #f1f1f1;
1976
+ # border-radius: 5px;
1977
+ # margin: 8px 0;
1978
+ # ">
1979
+ # <strong>Data Point:</strong> {data_point_colored}
1980
+ # </div>
1981
+ # <div style="
1982
+ # padding: 8px;
1983
+ # background: #f1f1f1;
1984
+ # border-radius: 5px;
1985
+ # ">
1986
+ # <strong>AI Reasoning:</strong> {reasoning_colored}
1987
+ # </div>
1988
+ # </div>
1989
+ # """,
1990
+ # unsafe_allow_html=True
1991
+ # )
1992
+
1993
+ # if not ai_recommendations:
1994
+ # st.info(
1995
+ # "No specific data points available for AI recommendations. "
1996
+ # "Ensure relevant columns are present (hour, shift, operator, duration, speed)."
1997
+ # )
1998
+
1999
+ # # ================= FOOTER ===========================
2000
+ # st.markdown("---")
2001
+ # st.markdown(
2002
+ # '<div class="footer">FatigueAnalyzer - Transforming Mining Safety with Intelligent Analytics | Contact: info@bukittechnology.com</div>',
2003
+ # unsafe_allow_html=True
2004
  # =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
2005
  st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
2006
 
 
2278
  st.markdown(
2279
  '<div class="footer">FatigueAnalyzer - Transforming Mining Safety with Intelligent Analytics | Contact: info@bukittechnology.com</div>',
2280
  unsafe_allow_html=True
2281
+ )
2282
+ # )