(文章)

22 週全國活動的平台做法:GPS 到場驗證、能量計分與手機效能

從規劃到開發完成不到 2 個月。到場驗證由伺服器計算,計分寫入能量帳本,名次與開獎由排程產生,圖片採 AVIF 分尺寸。

磨人開發團隊・2026-10-01

目錄

開發團隊配合教育部專案,建置 2026 全臺戶外教育季的活動平台,從規劃、設計到開發完成不到 2 個月。活動自 4 月 1 日進行到 8 月 31 日,共 22 週,涵蓋 180 多個場域、470 多堂課。活動全程在手機瀏覽器運行,不需下載 App。前端以 Nuxt 與 Mapbox GL JS 呈現互動地圖,後端是 Node.js 的 Express 與關聯式資料庫,另有排程處理對帳、名次與開獎。

獎勵帳務與防刷的通則另有專文,見有獎活動平台的帳務、防刷與預算控管。整體建置範圍見活動平台與後台。

玩家動作到計分的資料流

瀏覽器只送出玩家的動作,包括收集、答題、分享卡片、到場驗證與投稿心得。需要登入的請求帶著登入憑證,伺服器先檢查登入與活動狀態,再讀取該角色目前的進度,條件符合才寫入結果。

所有加分都寫成能量帳本中的一列,內容有使用者、年度、來源類型、能量與相關角色,來源類型共 9 種,帳本以使用者與年度建有索引。玩家的能量總和由帳本加總得出,彙總欄位在每次入帳後重算。角色進度則記在各角色自己的欄位,包括測驗是否通過、各階段是否已分享、是否完成到場驗證,以及心得編號。

圖 1瀏覽器只送動作與座標,距離、升級與計分都在伺服器完成

活動伺服器

  • API檢查登入與活動狀態,讀寫角色進度與能量帳本
  • 排程整點名次、每 6 小時對帳、每週四通知與每週五開獎
動作請求結果與圖檔網址

玩家的手機瀏覽器

  • Nuxt 前端地圖、課程與角色頁;寬度 1,000 像素以上用側邊面板
  • 瀏覽器暫存登入憑證、尚未登入時選好的夥伴與邀請碼
圖磚請求底圖圖磚

地圖服務

  • Mapbox提供底圖圖磚;場域標記與聚合由前端以圖層繪製

留在伺服器距離計算、冷卻判斷、升級條件與計分,瀏覽器只送座標與動作。

範圍:玩家動作到計分的資料流。

瀏覽器暫存的內容包括登入憑證,以及尚未登入時選好的夥伴與邀請碼。選夥伴的頁面由前端從角色清單隨機取出一隻,可以重抽;選定的結果先放在瀏覽器,登入後再寫入帳號,帳號設定後不能更改。10 個部會的課程資料怎麼整理成一份,見課程資料的合併與編號。

到場驗證:座標、距離與冷卻時間

玩家在課程頁按下驗證按鈕,前端呼叫一次 getCurrentPosition(),取得經緯度後送給伺服器。授權被拒絕與無法定位各有一則提示,玩家可以直接重試。

這個做法對應瀏覽器標準本來的分法。W3C 的 Geolocation 規格(目前為候選建議草案)把一次性取得位置的 getCurrentPosition() 與持續回報位置變化的 watchPosition() 分成兩個方法,並要求位置交給網頁應用之前須有使用者的明確同意(Cáceres 與 Grant,2026)。MDN 的說明另載明,呼叫 getCurrentPosition() 時使用者會收到授權提示,功能僅在安全環境(HTTPS)提供(MDN 的 getCurrentPosition 文件)。該規格的隱私段落建議只在需要時要求位置,用於原任務,完成後刪除,除非使用者明確允許保留。

伺服器以球面距離公式(Haversine,地球半徑取 6,371 公里)算出座標與場域之間的距離。超過 500 公尺,回覆請靠近場域後再試;在 500 公尺內,再看冷卻時間。冷卻時間依這一筆與上一筆驗證座標之間的移動距離分成 9 級,從 1 分鐘到 60 分鐘,距離越遠要等越久,相隔很遠的兩個場域,驗證之間會留出移動所需的時間。

圖 2伺服器先算距離、再看冷卻,兩關都過才寫入 20 點能量
  1. 確認登入與活動時間未登入或活動已結束,直接回覆對應訊息
  2. 確認角色進度已收集、位於 Lv2、尚未完成驗證,座標為數字
  3. 計算與場域的距離Haversine 公式,地球半徑 6,371 公里
  • 超過 500 公尺
    不計分回覆請靠近場域後再試
  • 500 公尺內,間隔短於冷卻時間
    不計分回覆需間隔的分鐘數
  • 500 公尺內,冷卻已過
    記錄到場並入帳 20 點接著重算彙總,判斷升級與徽章

範圍:到場驗證的判斷順序。

通過後,伺服器把該角色標記為已到場,寫入 20 點能量,重算彙總,再判斷是否升級與是否達成徽章條件。冷卻判斷需要上一筆座標,伺服器因此保留每次驗證請求的座標與時間。每次驗證都是玩家主動按下按鈕觸發的一次性讀取,沒有背景追蹤;活動辦法載明,原始座標於活動結束後 1 年內刪除。因裝置或環境導致驗證失敗的玩家,可以拍攝含場域標示的照片,向客服申請人工驗證。

計分:能量帳本、升級條件與徽章

角色分三個階段。每個動作完成後,伺服器都呼叫同一個升級判斷,條件齊了就升一級;同一階段內的動作沒有先後順序。

升級需完成的動作各動作入帳
取得角色(Lv1)在地圖上收集課程對應的角色收集 5 點
升到 Lv2通過第一題測驗,並分享卡片測驗 3 點、分享 2 點
升到 Lv3通過第二題測驗,分享卡片,完成到場驗證並投稿心得測驗 3 點、分享 2 點、到場 20 點、心得 30 點
角色圖鑑頁:上方三格說明三個階段,下方是各階段的角色卡片,標示 Lv1 至 Lv3。
角色圖鑑頁:上方三格說明三個階段,下方是各階段的角色卡片,標示 Lv1 至 Lv3。

收集與每次升級時,該角色的兩項能力值各自乘上稀有度,累計到玩家身上。兩項能力值合計是戰力榜的分數,能量榜的分數則是能量彙總。

徽章共 30 枚,分收集 21、任務 4、好友 5 三類,依觸發方式分成 24 枚里程碑型與 6 枚累積型。里程碑型在達成條件時一次發放,能量從 20 點到 2,000 點不等;發放時對使用者與徽章編號做唯一性寫入,只有真的新增了一列才入帳,同一枚徽章重複觸發也不會重複入帳。累積型徽章記錄累計次數,能量在每次動作當下就已入帳。

徽章的影響有研究可循。Hamari 在點對點交易平臺做了兩年的現場實驗,第一年 1,410 名使用者沒有徽章,第二年 1,579 名有徽章,有徽章的一組發出更多交易提案、完成更多交易,也留下更多留言(Hamari,2017);遊戲化實證研究的回顧則指出,效果高度取決於實施情境與使用者(Hamari 等,2014)。兩項研究都不是以戶外活動為對象,這裡只取設計方向。

能量再換成抽獎券,每 100 點 1 張,無條件捨去,持有的張數就是開獎時的權重。

排程:名次、對帳與開獎

排程以臺北時區執行,定時作業有四項。

作業時間內容
名次快照每小時整點重算能量榜與戰力榜,覆寫目前名次,並另存一份歷史快照
對帳每 6 小時以帳本重算每位玩家的能量彙總,核對里程碑型徽章與對應能量是否齊全,校正累積型徽章的次數
重點課程通知每週四 10:30依週排程表寄出本週重點課程,只寄給已啟用通知的玩家
開獎每週五 20:00讀取該週獎項設定,依券數加權抽出得主

名次依分數由高到低排序,分數相同者以較早得分的時間排前面。排行榜讀取預先算好的前 100 名,查詢時不必排序所有玩家;名字中間以星號遮蔽,不需登入即可查看。活動截止後的最後一次快照在 9 月 1 日 00:00,最終名次以該次快照為準。

開獎時先讀該週的獎項設定,展開成名額清單,每週 75 個名額,月底加碼的週次再加 3 個。接著依券數做加權抽取,每抽出一位就移出名單,同一位玩家一週最多得一個獎項。抽完再把獎項順序洗牌,得主與獎項的配對隨機一次。能量獎由排程直接寫入帳本,並更新彙總。

每週的重點課程由週排程表決定。表中每週一筆,記錄起訖日與課程編號,從第 2 週到第 22 週共 21 筆,其中第 2 至 20 週有課程,每週 1 到 13 門不等;地圖頁的本週重點課程視窗與週四通知信,都依今天落在哪一週取資料。

圖 3開獎固定在每週五 20:00,月底的 5 週另有加碼
開獎重點課程
149131822
  • 每週
    週五 20:00
    每週一組
  • 月底
    加碼 5 次

依週排程表與開獎設定繪製,每一格是一週,標記位於各週中點。第 1 週沒有開獎與重點課程,第 21、22 週沒有重點課程。

活動結束時的切換方式

前後端各保存一份截止時間,同為 2026 年 8 月 31 日 23:59:59(臺北時間)。前端依瀏覽器時鐘決定是否顯示結束版,只影響畫面;伺服器在收集、答題、分享卡片、到場驗證與投稿心得五類動作前,掛上同一個活動狀態檢查,截止後回覆「活動已結束」,不寫入任何紀錄。

活動結束版首頁:標示活動已結束,互動地圖、角色圖鑑與最終排名仍開放瀏覽。
活動結束版首頁:標示活動已結束,互動地圖、角色圖鑑與最終排名仍開放瀏覽。

登入、瀏覽地圖與課程、查看排行榜與個人紀錄不經過這個檢查,結束後照常可用。前端收到「活動已結束」會顯示提示,按鈕不會停在無反應的狀態。排行榜不需登入即可查看,名次區間與獎品留在畫面上,作為得獎名次的對外依據。同樣把線下活動搬上網路、並用積分與邀請帶動參與的另一種做法,見海外教育博覽會線上化。

活動結束後的排行榜:標示本屆排行榜已截止,分為戰力榜與能量榜兩個分頁,下方列出名次區間與獎品。
活動結束後的排行榜:標示本屆排行榜已截止,分為戰力榜與能量榜兩個分頁,下方列出名次區間與獎品。

手機上的載入:地圖聚合與圖片尺寸

全臺場域以 GeoJSON 資料來源交給 Mapbox GL JS,啟用聚合(clustering):聚合半徑參數 50,放大到縮放等級 15 以前都會聚合。聚合圈依場域數分四級,圓圈與顏色隨數量變化。場域標記與名稱畫在地圖圖層上,單一場域不會產生獨立的頁面元素;標記圖只登記一次,所有場域共用。地圖範圍限制在臺灣周邊,最大縮放等級 18。

桌機螢幕錄影:由全臺縮放至單一場域,滑過場域顯示名稱。

場域清單一次取回,網路不穩時最多嘗試 3 次,點開某個場域才讀取該場域的課程與心得。星期篩選在瀏覽器內對已取回的課程過濾,不必重新查詢。玩家是否已收集,伺服器以一次批次查詢取得該頁全部課程的結果,再用集合比對,不逐筆查詢。篩選選項這類不常變動的資料,伺服器快取 10 分鐘,前端查詢結果同樣保鮮 10 分鐘。版面在寬度 1,000 像素以上使用左側面板,以下改為底部預覽卡,點開後再展開。

手機螢幕錄影:在瀏覽器直接縮放與拖曳互動地圖,不需安裝。
成員用力推動大儀表的指針

角色圖共 5,280 個 AVIF,依用途分五種尺寸,後端回傳每隻角色的五個網址,前端依畫面取用。地圖與課程列表用約 2 KB 的預覽圖,點開角色詳情才載約 21 KB 的大圖,分享卡約 44 KB。AVIF 支援透明與有損、無損壓縮,Chrome、Firefox、Safari 等主要瀏覽器都支援(AOMedia 的說明)。尺寸與輸出流程見大型活動的角色系統。

圖檔回應帶一年的快取期限,回訪的玩家直接使用瀏覽器快取。前端建置時移除圖片的預取連結,圖片等畫面上的 img 元素要顯示時才載入,5,280 個圖檔不會在進站時同時預取。

不適合的情況

  • 活動期不到一個月。整點名次、每 6 小時對帳與每週開獎的設計用不上,活動頁加報名表就足夠。
  • 終點不在實體場域。到場驗證需要場域座標,純線上活動沒有這個步驟。
  • 沒有獎品與排名。能量帳本與抽獎券換算可以省略,只保留收集與進度。

開始前要準備什麼

  • 活動期間與截止時間,以及截止當下要切換的畫面
  • 場域清單與座標,以及認定到場的距離範圍
  • 每個階段要完成的動作,與各動作的能量
  • 獎項、開獎時間與名額,以及排名的計算方式
  • 授權定位、個資與抽獎的辦法,由主辦方確認

備齊之後,可以討論活動的規劃,說明活動期間、場域與預計規模。

(聯絡)

Start a project.

三個步驟,取得可判斷的做法與預算區間。

  1. 01預約第一場會議:選擇時段,不需要完整規格。
  2. 02線上諮詢 15 至 30 分鐘:取得做法方向、預算區間與時程草案。
  3. 03檢視素材後,約 3 至 5 個工作天提供報價單暨交付規格明細表。
信箱
hello@polish-design.com.tw
通訊地址
(104) 台北市中山區植福路191-1號3F

預約第一場會議

週一至週五 16:00–18:00線上 30 分鐘

先選時段,再用 Google 帳號或信箱確認,預約完成可加入行事曆。

選擇時段

或先送出資料

還沒想好時段,可以先留下專案內容,專人以信箱回覆。送出後也能接著預約。

補充資料(選填):服務項目、目前階段、現有連結、得知管道

資料僅用於本次專案評估。

ISO/IEC 27001:2022 證書

(Certificate)

ISO/IEC 27001:2022

驗證機構
ARES International Certification
驗證範圍
互動沉浸式 3D 系統之開發流程,及網路與基礎設施之維運與管理。

到驗證機構網站查證