第一階段(普獎)→ 第二階段(大獎)跨階段中獎資格全流程解析
大會報到是整個年會抽獎流程的起始步驟,也是確認參與者身份與出席的第一道關卡。當參加者抵達會場後,透過掃描專屬的 QR Code 或由志工協助,系統將自動記錄其
event_checked_in = True
的狀態。這個步驟是後續所有流程的前提條件,無論是節目報到、投票還是抽獎,都必須先通過大會報到才能參與。系統會同步記錄報到時間 event_checkin_at
及報到方式 event_checkin_method(可能為 QR 掃描、手動輸入帳號等),作為出席紀錄的一部分。在全流程模式
full_flow 下,大會報到完成後,參加者的手機頁面將自動引導至下一步驟——節目報到。系統同時支援代理報到功能
operator_proxy_checkin,讓執行秘書可以透過操作員後台為社員批量報到,特別適用於年長社友或不熟悉手機操作的參加者。報到數據會即時反映在管理員控制台的統計面板上,讓大會工作人員可以隨時掌握到場率。
第一階段普獎抽獎是年會的核心環節之一。管理員透過後台的抽獎控制面板,選擇 Phase 1 的獎品進行抽獎。系統的核心函式
get_raffle_eligible_attendees(phase=1) 會從資料庫中篩選出所有符合 Phase 1
要求的參加者——只需完成大會報到(event_checked_in = True)即可。Phase 1
不要求節目報到、不要求投票、不要求在場確認,這是最寬鬆的資格門檻,目的是讓所有到場的參加者都有機會獲得普獎。系統採用密碼學安全的隨機數生成器
SystemRandom 進行抽獎,確保公平性。每次抽獎會標記中獎者的 has_drawn = True,並建立
RaffleResult 記錄(包含 phase=1)。普獎通常數量較多(如 200 份),可使用批量抽獎 API
draw_batch 或一次性全抽 draw_all_remaining
來加速流程。中獎者在同一階段內不會重複中獎,但最關鍵的改動是——Phase 1 中獎者不再被排除於 Phase 2
之外,只要在場確認即可繼續參加大獎抽獎。
節目報到是全流程模式 full_flow 與 full_flow_with_presence
模式下的第二道關卡。當大會正式進入節目表演階段後,管理員會開啟節目報到功能,參加者需要再次掃描 QR Code 或由志工協助確認,系統將設定
show_checked_in = True。此步驟的設計目的在於確保參加者確實留在會場觀賞節目,而非報到後即離開。在某些簡化模式下(如
event_only 或
direct_vote),節目報到步驟會被自動跳過,系統會直接將狀態設為已完成。節目報到完成後,參加者才能進入投票環節。系統會檢查前一步驟的大會報到是否已完成——若未完成大會報到就直接嘗試節目報到,系統會友善提示「請先完成大會報到」。這個階層式的報到機制確保了活動參與的完整性,同時也讓主辦方可以精確統計各階段的在場人數。節目報到的時間戳記也會被保存,用於後續的出席分析報告。
投票是第一階段抽獎資格的最後一個前提條件。根據預設的階段要求 raffle_phase_requirements,Phase 1 要求
has_voted = True,意味著參加者必須完成投票才能進入普獎抽獎池。投票系統支援加權評分機制——不同職位的參加者(如社長、總監等)的投票分數會乘以對應的權重係數
vote_weight,確保公平性。投票結果會即時更新到計分板 Scoreboard
上,讓全場可以觀看各表演節目的得分排名。系統會在投票前檢查前置條件:在 full_flow 模式下必須先完成節目報到,在
event_only 模式下只需大會報到,在 direct_vote 模式下則無需任何報到步驟。當管理員將模式設為
disabled 或 confirm_presence
時,投票功能會被完全關閉。一旦參加者完成投票(即至少對一個表演投過分),系統會自動標記
has_voted = True,此參加者即正式具備第一階段抽獎資格。投票關閉時機通常在所有表演結束後,由管理員手動切換模式。
在場確認是 Phase 2 大獎抽獎的獨有前置條件,也是整個系統中最重要的防弊機制。Phase 2 的階段要求中額外增加了
presence_confirmed = True,這意味著即使參加者已完成報到、投票並中了普獎,若未完成在場確認,仍然無法參加大獎抽獎。在場確認有多種實現方式:(1)QR
Code 重新掃描——管理員將模式切換至 confirm_presence 或
full_flow_with_presence,參加者重新掃描入場 QR Code 即自動標記在場;(2)GPS 定位驗證——啟用
presence_gps_enabled 後,系統使用 Haversine 公式計算參加者手機座標與會場座標的距離,若在容許半徑內(預設 500
公尺)則確認在場;(3)志工手動確認——由現場志工透過操作員後台手動標記。管理員可以透過「開啟在場確認窗口」按鈕控制確認的時機——通常在普獎抽完後、大獎抽獎前開啟這個窗口,讓還在現場的人有
5-10 分鐘的時間完成確認。窗口關閉後,未確認的人將無法參加 Phase 2。管理員也可以使用 reset_all_presence
功能重置所有人的在場狀態,重新開始確認流程。
Phase 2 大獎抽獎採用精密的「阻擋性獎品」排除機制。每個 Phase 1 獎品都有 excludes_from_next_phase
屬性:普獎設為 False(中獎不阻擋 Phase
2),其他獎項(如特別獎)設為 True(中獎阻擋 Phase 2)。因此 Phase 2
的候選池 = 所有完成大會報到的人中,排除「中了阻擋性獎品的人」和「Phase 2 已中獎者」,再篩選
presence_confirmed = True。舉例:300 人大會報到 → 200 人中了普獎(不阻擋)→ 5 人中了特別獎(阻擋)→ Phase 2
候選池 = 300 - 5 = 295 人中有在場確認的人。普獎中獎者和完全沒中獎的人都可以參加 Phase 2。
Phase 2 大獎抽獎是整個年會的高潮時刻。與普獎不同,大獎通常數量稀少但價值極高(例如 1 萬元禮券、高級家電等),因此管理員通常會逐一抽出
draw_phase/2 或針對特定獎品抽出
draw_prize/{prize_id},每次抽出一位中獎者搭配全場螢幕的動畫展示效果。系統的抽獎流程與 Phase 1 相同——呼叫
get_raffle_eligible_attendees(phase=2) 篩選合格者,然後使用 SystemRandom
隨機抽出。但因為 Phase 2 的篩選條件更嚴格(多了在場確認),合格者池相對較小,這也使得大獎更為珍貴。中獎者被抽出後,系統會建立
RaffleResult(phase=2)
記錄,並在管理員控制台和參加者螢幕上同步顯示中獎資訊。中獎者需要在現場完成領獎流程——包括到指定領獎站出示身份、在平板上簽名確認,系統會記錄領獎時間
claimed_at、領獎站 claim_source、以及電子簽名圖檔
signature_path。若中獎者未在規定時間內領獎,管理員可以執行棄獎 forfeit
操作,將該獎品名額退回可抽狀態,讓其他合格者有機會中獎。
這是本次系統升級的核心改動,也是解決「200
人普獎中獎後如何參加大獎抽獎」問題的關鍵邏輯。在舊版系統中,get_raffle_eligible_attendees()
函式使用全局排除機制——一旦參加者的 has_drawn = True 或已存在任何
RaffleResult 記錄,就會被排除在所有階段的抽獎池之外。這意味著 Phase 1 普獎的 200
位中獎者,即使仍在現場且已通過在場確認,也完全無法參加 Phase 2 大獎抽獎。新版系統改為按階段隔離排除——查詢已中獎者時加入
RaffleResult.phase == phase 條件,只排除同一階段的已中獎者。例如查詢 Phase 2 合格者時,只排除 Phase 2
已中獎者,Phase 1 的中獎者不受影響。同時,attendee_meets_raffle_requirements() 也移除了全局
has_drawn 檢查,讓跨階段資格判斷更加準確。舉例來說:假設有 300 位參加者全部完成報到與投票,其中 200 人在 Phase 1
中了普獎。在舊版系統中 Phase 2 只有 100 位合格者;在新版系統中,只要這 200 人之中有人通過在場確認,他們也會出現在 Phase 2
的合格者名單中,大幅增加了大獎抽獎的參與度。has_drawn
欄位仍然保留在系統中作為「曾經中獎」的輔助統計標記,用於管理後台的統計顯示,但不再作為跨階段排除的依據。
| 條件 | Phase 1(普獎) | Phase 2(大獎) |
|---|---|---|
大會報到 event_checked_in |
✅ 必須 | ✅ 必須 |
節目報到 show_checked_in |
❌ 不需要 | ❌ 不需要 |
投票 has_voted |
❌ 不需要 | ❌ 不需要 |
在場確認 presence_confirmed |
❌ 不需要 | ✅ 必須 |
| 同階段重複中獎 | ❌ 不允許 | ❌ 不允許 |
| 普獎中獎者 | ✅ 可參加 Phase 2(excludes_from_next_phase = False) | |
| 其他獎項中獎者 | ❌ 不可參加 Phase 2(excludes_from_next_phase = True) | |
| Phase 1 未中獎者 | ✅ 可參加 Phase 2(在場確認即可) | |