diff --git a/README.md b/README.md index 6ac3997..db04665 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,19 @@ 5. **Stage 3 — 투표** (큰 화면에 QR, 모바일 → `/?mode=vote`) 6. **시상** (`/?mode=ceremony&token=mlops2026`) -## 실행 — Docker (한 줄) +## 실행 — Docker + +```bash +./start.sh # LAN IP 자동 감지 + PUBLIC_BASE_URL 세팅 + 컨테이너 기동 +``` + +또는 raw 방식 (LAN IP 수동): + +```bash +PUBLIC_BASE_URL="http://192.168.0.47:8501" docker compose up -d --build +``` + +또는 최소 (LAN IP 없이, 어드민에서 나중에 override): ```bash docker compose up -d --build @@ -24,7 +36,7 @@ docker compose up -d --build docker compose down # 종료 (데이터 보존) ``` -**ADMIN_TOKEN**: `mlops2026` (외우기 쉬운 고정값). 변경하려면 `docker-compose.yml`의 `ADMIN_TOKEN:` 값 직접 수정 후 `docker compose up -d --build`. +**ADMIN_TOKEN**: `mlops2026` (외우기 쉬운 고정값). 변경하려면 `docker-compose.yml`의 `ADMIN_TOKEN:` 값 직접 수정 후 재기동. ## URL diff --git a/app.py b/app.py index ee4f6df..7ee5416 100644 --- a/app.py +++ b/app.py @@ -58,16 +58,16 @@ SHOW_CSS = """ .show-cat-card { border-radius: 14px; padding: 18px; - min-height: 480px; + min-height: 360px; } .show-cat-T1 { background: linear-gradient(135deg, #ffb84d, #ff8c00); color: #222; } .show-cat-T2 { background: linear-gradient(135deg, #4dffd2, #2a8e7e); color: #1a1a1a; } .show-cat-T3 { background: linear-gradient(135deg, #ff4d6d, #b83a55); color: white; } .show-cat-T4 { background: linear-gradient(135deg, #a64dff, #6a2eaf); color: white; } -.show-cat-title { font-size: 32px; font-weight: 800; margin-bottom: 4px; } -.show-cat-tagline { font-size: 16px; font-style: italic; margin-bottom: 4px; } +.show-cat-title { font-size: 36px; font-weight: 800; margin-bottom: 4px; } +.show-cat-tagline { font-size: 18px; font-style: italic; margin-bottom: 4px; } .show-cat-tone { font-size: 14px; opacity: 0.85; margin-bottom: 12px; } -.show-cat-item { font-size: 17px; line-height: 1.45; padding: 4px 0; } +.show-cat-item { font-size: 19px; line-height: 1.55; padding: 4px 0; } .show-vote-counter { font-size: 96px; text-align: center; font-weight: 900; padding: 16px 0; } .show-vote-caption { font-size: 36px; text-align: center; color: #555; padding: 12px 0; } @@ -468,6 +468,17 @@ def render_stage_vote(data): unsafe_allow_html=True, ) + votes = data.get("votes", []) + total = len(data.get("people", [])) + voted = len(votes) + pct = voted / total if total else 0 + + st.markdown( + f'
{voted} / {total}
', + unsafe_allow_html=True, + ) + st.progress(pct) + vote_url = compute_vote_url() qr_png = make_qr_png(vote_url) @@ -479,16 +490,6 @@ def render_stage_vote(data): unsafe_allow_html=True, ) - votes = data.get("votes", []) - total = len(data.get("people", [])) - voted = len(votes) - pct = int(100 * voted / total) if total else 0 - st.markdown( - f'
{voted} / {total}
', - unsafe_allow_html=True, - ) - st.progress(pct / 100 if total else 0) - def render_voter(): if not can_accept_votes(load_data()): diff --git a/docker-compose.yml b/docker-compose.yml index 8147f02..ac5c830 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,10 +6,13 @@ services: ports: - "${PORT:-8501}:8501" environment: - ADMIN_TOKEN: ${ADMIN_TOKEN:-change-me} - DATA_PATH: /app/hackathon.json + # 외우기 쉬운 고정 token. 변경하려면 여기 값만 수정. + ADMIN_TOKEN: mlops2026 + DATA_PATH: /app/data/hackathon.json + PUBLIC_BASE_URL: ${PUBLIC_BASE_URL:-} volumes: - # 단일 데이터 파일. 호스트 ↔ 컨테이너 read-write mount. - # 호스트에서 jq/vi 편집 가능, 앱이 votes 추가 시 그대로 반영. - - ./hackathon.json:/app/hackathon.json + # 단일 데이터 디렉터리 마운트. + # 첫 부팅 시 entrypoint.sh가 assign_teams.py 실행하여 hackathon.json 시드. + # 이후 부팅은 기존 파일 보존. + - ./data:/app/data restart: unless-stopped diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..1f2abf2 --- /dev/null +++ b/start.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# 호스트 LAN IP 자동 감지 → PUBLIC_BASE_URL 세팅 → 컨테이너 기동 +set -euo pipefail +cd "$(dirname "$0")" + +LAN_IP=$(ipconfig getifaddr en0 2>/dev/null || ip -4 addr show 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '^127\.' | head -1 || echo "") +PORT=${PORT:-8501} + +if [[ -n "$LAN_IP" ]]; then + export PUBLIC_BASE_URL="http://${LAN_IP}:${PORT}" + echo "[start] PUBLIC_BASE_URL=${PUBLIC_BASE_URL} (자동 감지)" +else + echo "[start] LAN IP 감지 실패. 어드민에서 PUBLIC_BASE_URL 직접 설정 필요." +fi + +exec docker compose up -d --build "$@"