| |
| |
|
|
| """Prefero โ Home page (main entry point for the multi-page app).""" |
|
|
| from __future__ import annotations |
|
|
| import os |
| from pathlib import Path |
|
|
| import streamlit as st |
|
|
| from utils import init_session_state, language_banner, sidebar_branding, slowbro_next_step |
|
|
| st.set_page_config( |
| page_title="Prefero - DCE Analysis Tool", |
| page_icon="๐งฎ", |
| layout="wide", |
| ) |
|
|
| init_session_state() |
| sidebar_branding() |
|
|
| |
| language_banner() |
|
|
| st.markdown( |
| '<div style="text-align:right; margin-top:-6px; margin-bottom:4px;">', |
| unsafe_allow_html=True, |
| ) |
| st.markdown( |
| "", |
| help=( |
| "We respect and celebrate linguistic and cultural diversity. " |
| "The transliterations above represent our best effort to render " |
| "\"Prefero\" faithfully in each writing system. We acknowledge that " |
| "automated transliteration may not perfectly capture every nuance. " |
| "If you feel a translation could be improved, we warmly welcome " |
| "your feedback โ please reach out via GitHub Issues. Thank you!" |
| ), |
| ) |
| st.markdown("</div>", unsafe_allow_html=True) |
|
|
| |
| st.title("Prefero") |
| st.caption("Discrete Choice Experiment Analysis") |
| st.markdown( |
| """ |
| Welcome to **Prefero**, a **completely code-free** interactive tool |
| for specifying, estimating, and comparing discrete-choice models. |
| |
| No programming required โ just upload your data, point and click, and let |
| Slowbro handle the heavy lifting. Whether you're a seasoned econometrician |
| or running your first choice experiment, everything works through this |
| guided interface. |
| """ |
| ) |
|
|
| |
| st.subheader("Workflow") |
|
|
| steps = [ |
| ("1", "Data", "Load or simulate a choice dataset.", "๐"), |
| ("2", "Model", "Configure CL, MXL, or Latent Class models.", "โ๏ธ"), |
| ("3", "Results", "Inspect estimates, WTP, and predictions.", "๐"), |
| ("4", "Compare", "Compare models side-by-side.", "๐"), |
| ("5", "Bootstrap", "Bootstrap inference for robust SEs.", "๐ฏ"), |
| ("6", "Report", "Generate a professional analysis report.", "๐"), |
| ("7", "Community", "Discuss methods and share insights.", "๐ฌ"), |
| ] |
|
|
| cols = st.columns(7) |
| for col, (num, title, desc, icon) in zip(cols, steps): |
| with col: |
| with st.container(border=True): |
| st.markdown(f"### {icon}") |
| st.markdown(f"**Step {num}: {title}**") |
| st.caption(desc) |
|
|
| st.divider() |
|
|
| |
| _NAV_IMG = ( |
| "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites" |
| "/pokemon/other/official-artwork/80.png" |
| ) |
|
|
| _j1, _j2 = st.columns([1, 4]) |
| with _j1: |
| st.image(_NAV_IMG, width=80) |
| with _j2: |
| st.markdown( |
| "<p style='margin:0; color:gray; font-size:0.85em;'>" |
| "Ready? Slowbro will walk you through every step.</p>", |
| unsafe_allow_html=True, |
| ) |
| if st.button( |
| "๐ Begin the journey with Slowbro", |
| key="_nav_begin", |
| use_container_width=True, |
| type="primary", |
| ): |
| st.switch_page("pages/1_๐_Data.py") |
|
|
| |
| st.divider() |
|
|
| |
| _slowpoke_url = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/79.png" |
| _shellder_url = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/90.png" |
| _slowbro_url = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/80.png" |
|
|
| st.markdown("#### The Tale of Slowbro โ Our Mascot") |
|
|
| _story_col1, _story_col2, _story_col3 = st.columns(3) |
|
|
| with _story_col1: |
| st.image(_slowpoke_url, width=180, caption="Slowpoke") |
| st.markdown( |
| """ |
| Once upon a time, there was a **Slowpoke** who spent its days |
| by the river, staring blankly at the water, occasionally |
| dipping its tail in to fish... very, very slowly. |
| """ |
| ) |
|
|
| with _story_col2: |
| st.image(_shellder_url, width=140, caption="Shellder") |
| st.markdown( |
| """ |
| One day, a **Shellder** swam by and clamped down hard on |
| Slowpoke's tail. About five minutes later, Slowpoke finally |
| noticed: *"Huh? Did something just bite me...?"* |
| """ |
| ) |
|
|
| with _story_col3: |
| st.image(_slowbro_url, width=180, caption="Slowbro") |
| st.markdown( |
| """ |
| And just like that, **Slowpoke evolved into Slowbro!** |
| Shellder never let go, and Slowbro never bothered to |
| check โ they've been stuck together ever since. |
| """ |
| ) |
|
|
| st.markdown("---") |
|
|
| _bro_col1, _bro_col2 = st.columns([1, 3]) |
|
|
| with _bro_col1: |
| st.image(_slowbro_url, width=120) |
|
|
| with _bro_col2: |
| st.markdown( |
| """ |
| Now, this Slowbro spends every day running **discrete choice models** for everyone: |
| Mixed Logit, Latent Class, GMNL, Bootstrap... |
| each one more exhausting than the last. |
| |
| > *Slowbro is tired. When Slowbro is tired, Slowbro needs coffee.* โ |
| """ |
| ) |
| |
| _coffee_url = os.environ.get("COFFEE_URL", "https://buymeacoffee.com/preferohz") |
| _bmc_logo = "https://cdn.buymeacoffee.com/buttons/bmc-new-btn-logo.svg" |
|
|
| _btn_style = ( |
| "display:flex; align-items:center; justify-content:center; " |
| "gap:8px; padding:12px 16px; border-radius:8px; " |
| "font-weight:600; font-size:0.95em; height:48px; " |
| "text-decoration:none; cursor:pointer;" |
| ) |
|
|
| st.markdown( |
| f"<a href='{_coffee_url}' target='_blank' style='" |
| f"{_btn_style} max-width:300px; background:#FFDD00; color:#000;'>" |
| f"<img src='{_bmc_logo}' width='22' style='flex-shrink:0;'/>" |
| f"Buy Slowbro a Coffee</a>", |
| unsafe_allow_html=True, |
| ) |
|
|