| """ |
| app.py β Main Streamlit entry point for No-CelH Self-Learning RMS |
| Run: streamlit run app.py |
| Hugging Face Spaces: set SDK=streamlit, app_file=app.py |
| """ |
|
|
| import streamlit as st |
|
|
| st.set_page_config( |
| page_title="No-CelH Β· Self-Learning RMS", |
| page_icon="π", |
| layout="wide", |
| initial_sidebar_state="expanded", |
| menu_items={ |
| "Get Help": "https://www.wcoomd.org/en/topics/enforcement-and-compliance/activities-and-programmes/risk-management.aspx", |
| "Report a bug": None, |
| "About": "No-CelH: Self-Learning RMS β WCO Accredited Expert Simulation Tool\n\nBuilt on DATE + gATE Active Learning (Kim et al. 2022, IEEE TKDE)", |
| }, |
| ) |
|
|
| import page1_intro |
| import page2_risk_register |
| import page3_simulation |
| import page4_results |
| import page5_optimisation |
| from styles import WCO_GOLD, WCO_NAVY, WCO_BORDER, WCO_CARD_BG, WCO_MUTED, WCO_RED, WCO_GREEN |
|
|
| PAGES = { |
| "π Introduction & Architecture": page1_intro, |
| "π Risk Register & Matrix": page2_risk_register, |
| "π Simulation Engine": page3_simulation, |
| "π Simulation Results": page4_results, |
| "π Bandwidth Optimisation": page5_optimisation, |
| } |
|
|
| def sidebar(): |
| with st.sidebar: |
| st.markdown(f""" |
| <div style="text-align:center;padding:20px 10px 14px;"> |
| <div style="font-size:42px;">π</div> |
| <div style="color:{WCO_GOLD};font-family:'Playfair Display',Georgia,serif; |
| font-size:16px;font-weight:700;margin-top:8px;line-height:1.3;"> |
| No-CelH<br/>Self-Learning RMS |
| </div> |
| <div style="color:{WCO_MUTED};font-size:10px;margin-top:6px; |
| font-family:'IBM Plex Mono',monospace;letter-spacing:0.06em;"> |
| WCO ACCREDITED Β· v2.0 |
| </div> |
| </div> |
| <hr style="border-color:{WCO_BORDER};margin:0 0 16px;"/> |
| """, unsafe_allow_html=True) |
|
|
| st.markdown(f""" |
| <div style="color:{WCO_GOLD};font-size:11px;font-weight:600; |
| letter-spacing:0.1em;text-transform:uppercase; |
| padding:0 4px;margin-bottom:8px;">Navigation</div> |
| """, unsafe_allow_html=True) |
|
|
| selected = st.radio("", list(PAGES.keys()), |
| key="nav_page", label_visibility="collapsed") |
|
|
| st.markdown(f"<hr style='border-color:{WCO_BORDER};margin:16px 0;'/>", |
| unsafe_allow_html=True) |
|
|
| |
| sim_ready = "sim_df" in st.session_state |
| st.markdown(f""" |
| <div style="background:{WCO_CARD_BG};border:1px solid {WCO_BORDER}; |
| border-radius:10px;padding:14px;"> |
| <div style="color:{WCO_GOLD};font-size:11px;font-weight:600; |
| text-transform:uppercase;letter-spacing:0.08em;margin-bottom:10px;"> |
| Session Status |
| </div> |
| <div style="font-size:12px;line-height:2.1;color:#8BAAD4;"> |
| <span style="color:{'#44CC88' if sim_ready else WCO_MUTED};"> |
| {'β
' if sim_ready else 'β¬'}</span> Simulation Run<br/> |
| <span style="color:{'#44CC88' if 'rule_weights' in st.session_state else WCO_MUTED};"> |
| {'β
' if 'rule_weights' in st.session_state else 'β¬'}</span> Weights Configured<br/> |
| <span style="color:{'#44CC88' if 'sim_efficiency' in st.session_state else WCO_MUTED};"> |
| {'β
' if 'sim_efficiency' in st.session_state else 'β¬'}</span> Results Available |
| </div> |
| </div> |
| """, unsafe_allow_html=True) |
|
|
| if sim_ready: |
| df = st.session_state.sim_df |
| eff = st.session_state.get("sim_efficiency", {}).get("hybrid", {}) |
| st.markdown(f""" |
| <div style="background:{WCO_CARD_BG};border:1px solid {WCO_BORDER}; |
| border-radius:10px;padding:14px;margin-top:10px;"> |
| <div style="color:{WCO_GOLD};font-size:11px;font-weight:600; |
| text-transform:uppercase;letter-spacing:0.08em;margin-bottom:10px;"> |
| Last Simulation |
| </div> |
| <div style="font-size:12px;line-height:2.1;color:#8BAAD4;"> |
| π¦ Bills: <b style="color:#D0DCF0;">{len(df):,}</b><br/> |
| π΄ RED: <b style="color:{WCO_RED};">{(df['channel']=='RED').sum()}</b><br/> |
| π‘ YEL: <b style="color:{WCO_GOLD};">{(df['channel']=='YELLOW').sum()}</b><br/> |
| π’ GRN: <b style="color:{WCO_GREEN};">{(df['channel']=='GREEN').sum()}</b><br/> |
| π¨ Detected: <b style="color:{WCO_RED};"> |
| {(df['inspection_outcome']=='FRAUD_DETECTED').sum()}</b><br/> |
| π Efficiency: <b style="color:{WCO_GREEN};"> |
| {eff.get('efficiency_index',0):.3f}</b> |
| </div> |
| </div> |
| """, unsafe_allow_html=True) |
|
|
| st.markdown(f""" |
| <hr style="border-color:{WCO_BORDER};margin:16px 0 10px;"/> |
| <div style="color:{WCO_MUTED};font-size:10px;text-align:center;line-height:1.7;padding:0 4px;"> |
| Based on: Kim et al. (2022)<br/> |
| <i>Active Learning for Human-in-the-Loop Customs Inspection</i><br/> |
| IEEE TKDE Β· WCO Compendium<br/> |
| <span style="color:{WCO_GOLD};">WCO BACUDA Initiative</span> |
| </div> |
| """, unsafe_allow_html=True) |
|
|
| return selected |
|
|
|
|
| def main(): |
| selected = sidebar() |
| PAGES[selected].show() |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|