SHELLAPANDIANGANHUNGING commited on
Commit
cd900f0
·
verified ·
1 Parent(s): c1edd4a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -192
app.py CHANGED
@@ -1527,203 +1527,76 @@ def plot_chart(data, title):
1527
  )
1528
  return fig
1529
 
1530
-
1531
- # ==========================
1532
- # INSIGHT DISPLAY SECTION
1533
- # ==========================
1534
- col_insight1, col_insight2 = st.columns(2)
1535
-
1536
- with col_insight1:
1537
- if not top_ob.empty:
1538
- st.markdown("### OB HAULER Hazard Analysis")
1539
- ob_worsening = len(top_ob[top_ob['slope'] > 0])
1540
- ob_improving = len(top_ob[top_ob['slope'] < 0])
1541
- ob_one_time = len(top_ob[top_ob['slope'] == 0])
1542
- ob_avg_risk = top_ob['weekly_avg'].mean()
1543
- ob_max_risk = top_ob['weekly_avg'].max()
1544
-
1545
- # Always show 3 insights
1546
- ob_insights = [
1547
- f"{ob_worsening} out of 10 top hazard operators are showing <span class='trend-up'>worsening</span> trends.",
1548
- f"{ob_one_time} operators are classified as <b>One Time Event</b> (single-week activity).",
1549
- f"Average hazard: {ob_avg_risk:.2f} events/week (max: {ob_max_risk:.2f})."
1550
- ]
1551
- for insight in ob_insights:
1552
- st.markdown(
1553
- f"""
1554
- <div class="ai-insight-box">
1555
- <div class="ai-insight-title">Hazard Summary</div>
1556
- <p>{insight}</p>
1557
- </div>
1558
- """,
1559
- unsafe_allow_html=True
1560
- )
1561
- else:
1562
- st.info("No OB HAULER data for analysis.")
1563
-
1564
- with col_insight2:
1565
- if not top_coal.empty:
1566
- st.markdown("### HAULING COAL Hazard Analysis")
1567
- coal_worsening = len(top_coal[top_coal['slope'] > 0])
1568
- coal_improving = len(top_coal[top_coal['slope'] < 0])
1569
- coal_one_time = len(top_coal[top_coal['slope'] == 0])
1570
- coal_avg_risk = top_coal['weekly_avg'].mean()
1571
- coal_max_risk = top_coal['weekly_avg'].max()
1572
-
1573
- coal_insights = [
1574
- f"{coal_worsening} out of 10 top hazard operators are showing <span class='trend-up'>worsening</span> trends.",
1575
- f"{coal_one_time} operators are classified as <b>One Time Event</b> (single-week activity).",
1576
- f"Average hazard: {coal_avg_risk:.2f} events/week (max: {coal_max_risk:.2f})."
1577
- ]
1578
- for insight in coal_insights:
1579
- st.markdown(
1580
- f"""
1581
- <div class="ai-insight-box">
1582
- <div class="ai-insight-title">Hazard Summary</div>
1583
- <p>{insight}</p>
1584
- </div>
1585
- """,
1586
- unsafe_allow_html=True
1587
- )
1588
- else:
1589
- st.info("No HAULING COAL data for analysis.")
1590
  # ===============================================================
1591
- # RECOMMENDATIONS# ===============================================================
1592
- # PLOT FUNCTION — UPDATED: color for slope=0 is now #FFD700
1593
- # ===============================================================
1594
- def plot_chart(data, title):
1595
- if data.empty:
1596
- fig = go.Figure()
1597
- fig.add_annotation(
1598
- text="No Data",
1599
- x=0.5, y=0.5,
1600
- showarrow=False,
1601
- font_size=16
1602
- )
1603
- fig.update_layout(height=350, title=dict(text=title, x=0.5))
1604
- return fig
1605
 
1606
- data_sorted = data.sort_values('weekly_avg', ascending=False)
 
 
 
1607
 
1608
- def get_color(slope):
1609
- if slope == 0:
1610
- return "#FFD700" # Kuning untuk One Time Event
1611
- elif slope > 0:
1612
- if slope < 0.5:
1613
- return "#ffcdd2"
1614
- elif slope < 1.0:
1615
- return "#ef9a9a"
1616
- elif slope < 1.5:
1617
- return "#e57373"
1618
- else:
1619
- return "#d32f2f"
1620
- else: # slope < 0
1621
- if slope > -0.5:
1622
- return "#c8e6c9"
1623
- elif slope > -1.0:
1624
- return "#a5d6a7"
1625
- elif slope > -1.5:
1626
- return "#81c784"
 
 
 
 
 
1627
  else:
1628
- return "#388e3c"
1629
-
1630
- colors = [get_color(s) for s in data_sorted["slope"]]
1631
-
1632
- bar_trace = go.Bar(
1633
- x=data_sorted[col_operator].astype(str),
1634
- y=data_sorted["weekly_avg"],
1635
- marker=dict(
1636
- color=colors,
1637
- line=dict(width=2, color="rgba(0,0,0,0.2)")
1638
- ),
1639
- text=[f"{v:.1f}" for v in data_sorted["weekly_avg"]],
1640
- textposition="outside",
1641
- hovertemplate=(
1642
- "<b>%{x}</b><br>" +
1643
- "Weekly Avg: %{y:.2f}<br>" +
1644
- "Trend Slope: %{customdata[0]:+.3f}<br>" +
1645
- "Total Events: %{customdata[1]}<br>" +
1646
- "Weeks Active: %{customdata[2]}<br>" +
1647
- "<extra></extra>"
1648
- ),
1649
- customdata=np.stack([data_sorted["slope"], data_sorted["total_events"], data_sorted["n_weeks"]], axis=-1)
1650
- )
1651
-
1652
- fig = go.Figure(bar_trace)
1653
- fig.update_layout(
1654
- title=dict(text=f"<b>{title}</b>", x=0.5),
1655
- height=450,
1656
- margin=dict(l=50, r=20, t=60, b=120),
1657
- xaxis_title="<b>Operator Name</b>",
1658
- yaxis_title="<b>Weekly Avg Events</b>",
1659
- font=dict(family="Segoe UI", size=12),
1660
- bargap=0.3,
1661
- plot_bgcolor="rgba(0,0,0,0)",
1662
- paper_bgcolor="rgba(0,0,0,0)",
1663
- xaxis=dict(tickangle=45)
1664
- )
1665
- return fig
1666
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1667
 
1668
- # ==========================
1669
- # INSIGHT DISPLAY SECTION
1670
- # ==========================
1671
- col_insight1, col_insight2 = st.columns(2)
1672
-
1673
- with col_insight1:
1674
- if not top_ob.empty:
1675
- st.markdown("### OB HAULER Hazard Analysis")
1676
- ob_worsening = len(top_ob[top_ob['slope'] > 0])
1677
- ob_improving = len(top_ob[top_ob['slope'] < 0])
1678
- ob_one_time = len(top_ob[top_ob['slope'] == 0])
1679
- ob_avg_risk = top_ob['weekly_avg'].mean()
1680
- ob_max_risk = top_ob['weekly_avg'].max()
1681
-
1682
- # Always show 3 insights
1683
- ob_insights = [
1684
- f"{ob_worsening} out of 10 top hazard operators are showing <span class='trend-up'>worsening</span> trends.",
1685
- f"{ob_one_time} operators are classified as <b>One Time Event</b> (single-week activity).",
1686
- f"Average hazard: {ob_avg_risk:.2f} events/week (max: {ob_max_risk:.2f})."
1687
- ]
1688
- for insight in ob_insights:
1689
- st.markdown(
1690
- f"""
1691
- <div class="ai-insight-box">
1692
- <div class="ai-insight-title">Hazard Summary</div>
1693
- <p>{insight}</p>
1694
- </div>
1695
- """,
1696
- unsafe_allow_html=True
1697
- )
1698
- else:
1699
- st.info("No OB HAULER data for analysis.")
1700
-
1701
- with col_insight2:
1702
- if not top_coal.empty:
1703
- st.markdown("### HAULING COAL Hazard Analysis")
1704
- coal_worsening = len(top_coal[top_coal['slope'] > 0])
1705
- coal_improving = len(top_coal[top_coal['slope'] < 0])
1706
- coal_one_time = len(top_coal[top_coal['slope'] == 0])
1707
- coal_avg_risk = top_coal['weekly_avg'].mean()
1708
- coal_max_risk = top_coal['weekly_avg'].max()
1709
-
1710
- coal_insights = [
1711
- f"{coal_worsening} out of 10 top hazard operators are showing <span class='trend-up'>worsening</span> trends.",
1712
- f"{coal_one_time} operators are classified as <b>One Time Event</b> (single-week activity).",
1713
- f"Average hazard: {coal_avg_risk:.2f} events/week (max: {coal_max_risk:.2f})."
1714
- ]
1715
- for insight in coal_insights:
1716
- st.markdown(
1717
- f"""
1718
- <div class="ai-insight-box">
1719
- <div class="ai-insight-title">Hazard Summary</div>
1720
- <p>{insight}</p>
1721
- </div>
1722
- """,
1723
- unsafe_allow_html=True
1724
- )
1725
- else:
1726
- st.info("No HAULING COAL data for analysis.")
1727
  # ===============================================================
1728
  col_rec1, col_rec2 = st.columns(2)
1729
 
@@ -1801,7 +1674,6 @@ with col_insight2:
1801
  st.exception(e) # optionally show full traceback during dev
1802
 
1803
 
1804
-
1805
  # =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
1806
  st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
1807
 
 
1527
  )
1528
  return fig
1529
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1530
  # ===============================================================
1531
+ # CHARTS
1532
+ # ===============================================================
1533
+ col1, col2 = st.columns(2)
1534
+ with col1:
1535
+ st.plotly_chart(plot_chart(top_ob, "OB HAULER Operators (Hazard Gradient)"), use_container_width=True)
1536
+ with col2:
1537
+ st.plotly_chart(plot_chart(top_coal, "HAULING COAL Operators (Hazard Gradient)"), use_container_width=True)
 
 
 
 
 
 
 
1538
 
1539
+ # ===============================================================
1540
+ # AI INSIGHTS — tetap dalam bahasa Inggris, tanpa emoticon
1541
+ # ===============================================================
1542
+ col_insight1, col_insight2 = st.columns(2)
1543
 
1544
+ with col_insight1:
1545
+ if not top_ob.empty:
1546
+ st.markdown("### OB HAULER Analysis")
1547
+ ob_worsening = len(top_ob[top_ob['slope'] > 0])
1548
+ ob_improving = len(top_ob[top_ob['slope'] < 0])
1549
+ ob_one_time = len(top_ob[top_ob['slope'] == 0])
1550
+ ob_avg_risk = top_ob['weekly_avg'].mean()
1551
+ ob_max_risk = top_ob['weekly_avg'].max()
1552
+ ob_insights = []
1553
+ if ob_worsening > ob_improving:
1554
+ ob_insights.append(f"{ob_worsening} out of 10 top risk operators are showing <span class='trend-up'>worsening</span> trends.")
1555
+ else:
1556
+ ob_insights.append(f"{ob_improving} out of 10 top risk operators are showing <span class='trend-down'>improvement</span>.")
1557
+ if ob_one_time > 0:
1558
+ ob_insights.append(f"{ob_one_time} operators are classified as <b>One Time Event</b> (single-week activity).")
1559
+ ob_insights.append(f"Average risk: {ob_avg_risk:.2f} events/week (max: {ob_max_risk:.2f}).")
1560
+
1561
+ for insight in ob_insights:
1562
+ st.markdown(f"""
1563
+ <div class="ai-insight-box">
1564
+ <div class="ai-insight-title">Risk Summary</div>
1565
+ <p>{insight}</p>
1566
+ </div>
1567
+ """, unsafe_allow_html=True)
1568
  else:
1569
+ st.info("No OB HAULER data for analysis.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1570
 
1571
+ with col_insight2:
1572
+ if not top_coal.empty:
1573
+ st.markdown("### HAULING COAL Analysis")
1574
+ coal_worsening = len(top_coal[top_coal['slope'] > 0])
1575
+ coal_improving = len(top_coal[top_coal['slope'] < 0])
1576
+ coal_one_time = len(top_coal[top_coal['slope'] == 0])
1577
+ coal_avg_risk = top_coal['weekly_avg'].mean()
1578
+ coal_max_risk = top_coal['weekly_avg'].max()
1579
+ coal_insights = []
1580
+ if coal_worsening > coal_improving:
1581
+ coal_insights.append(f"{coal_worsening} out of 10 top risk operators are showing <span class='trend-up'>worsening</span> trends.")
1582
+ else:
1583
+ coal_insights.append(f"{coal_improving} out of 10 top risk operators are showing <span class='trend-down'>improvement</span>.")
1584
+ if coal_one_time > 0:
1585
+ coal_insights.append(f"{coal_one_time} operators are classified as <b>One Time Event</b> (single-week activity).")
1586
+ coal_insights.append(f"Average risk: {coal_avg_risk:.2f} events/week (max: {coal_max_risk:.2f}).")
1587
+
1588
+ for insight in coal_insights:
1589
+ st.markdown(f"""
1590
+ <div class="ai-insight-box">
1591
+ <div class="ai-insight-title">Risk Summary</div>
1592
+ <p>{insight}</p>
1593
+ </div>
1594
+ """, unsafe_allow_html=True)
1595
+ else:
1596
+ st.info("No HAULING COAL data for analysis.")
1597
 
1598
+ # ===============================================================
1599
+ # RECOMMENDATIONS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1600
  # ===============================================================
1601
  col_rec1, col_rec2 = st.columns(2)
1602
 
 
1674
  st.exception(e) # optionally show full traceback during dev
1675
 
1676
 
 
1677
  # =================== OBJECTIVE 6: Automated Insights & AI Recommendations =====================
1678
  st.subheader("OBJECTIVE 6: Instant Insights & Recommendations")
1679