我想解決什麼問題
喝水這件事的難處不在「不知道要喝」,而在喝得不夠規律—— 忙起來忘了,想起來就一次灌一大杯。
既有的提醒工具多半只記「今天喝了多少」,於是一次灌 2000ml 跟分八次慢慢喝, 在紀錄上完全一樣。這樣一來,提醒能改變的行為其實很有限。
我想做的是讓喝水的節奏本身變成有回饋的事, 而且回饋要立刻看得到、累積得起來。
動機與目標
喝水提醒 App 大多是同一套:設個間隔、跳通知、按「已喝水」。 按下去之後畫面沒有變化,所以那顆按鈕很容易就變成順手滑掉的東西。
看得見變化的提醒,才留得住。
所以,沃田把喝水的回饋設計成一座會成長的菜園。每喝一次水,就能獲得一次澆水機會; 細心照料後,蔬菜會慢慢長大、開花結果,最後還能收成並換取金幣,持續擴建自己的菜園。 使用者今天的每一次行動,都會立即反映在畫面上,打開程式就能看見自己的累積成果。
這樣的設計也十分符合使用情境。無論是讀書或工作時,大多數人都長時間坐在電腦前, 手機放在一旁往往容易被忽略;而桌面上的應用程式則始終位於視線範圍內, 讓使用者能在不打斷工作流程的情況下,隨時留意自己的喝水進度與菜園成長, 將健康習慣自然融入日常生活。
喝水這件事的難處不在「不知道要喝」,而在喝得不夠規律—— 忙起來忘了,想起來就一次灌一大杯。
既有的提醒工具多半只記「今天喝了多少」,於是一次灌 2000ml 跟分八次慢慢喝, 在紀錄上完全一樣。這樣一來,提醒能改變的行為其實很有限。
我想做的是讓喝水的節奏本身變成有回饋的事, 而且回饋要立刻看得到、累積得起來。
因為養成遊戲的節奏跟規律喝水天生吻合:作物要分次照顧才會長大, 一次澆再多水也沒有用——這正好就是喝水該有的樣子。
互動設計
這是整個系統最核心的互動規則,也是所有功能設計的基礎。 使用者每完成一次喝水紀錄,就立即獲得一次澆水機會, 讓每個健康行為都能即時轉化為遊戲中的成長回饋, 形成「喝水 → 澆水 → 成長 → 收成」的循環體驗。
這裡跑的就是 garden_logic.py 的規則。
拉一下滑桿,看同樣的水量、兩種喝法會差多少。
一次算 250ml,總共 1500 ml
一樣喝 1500 ml,但只分 1 次喝完
可澆 6 株
可澆 1 株
每個等級都會影響三項核心機制:解鎖所需的連續登入天數、作物成熟所需的澆水次數, 以及收成後可獲得的金幣數量。作物分級並非主觀設定,而是參考農業部「當季好蔬果」 公布的市場價格進行分類,讓遊戲機制更貼近真實情境。 此外,只要將滑鼠移至左側的作物圖示,即可預覽作物從種子、發芽、 生長到成熟的完整成長過程。
橫條的長度就是那一級的價錢範圍,四條共用同一把 0–1031 元的尺。 頂階的櫻桃一公斤 1031 元,初階的紅蘿蔔 28 元, 差了快 37 倍——所以頂階要連續 14 天才給解鎖。
每一張卡上的價錢,就是農業部公布的市場零售價;種子價則是還沒解鎖時, 想先種它要付的金幣。
一開始就能種,3 次澆水就成熟,適合剛養成習慣的時候。
連續 3 天解鎖,需要 4 次澆水,收成是初階的 2.5 倍。
連續 7 天解鎖,5 次澆水才成熟,市價已經是初階的三到九倍。
連續 14 天解鎖,6 次澆水,收成 100 金——菜價最高的那一群。
公式的每一項都查得到官方出處。拉拉看,數字會一項一項疊起來。
性別係數只乘在體重基數上,不乘在加成。算完再取
max(結果, 1500) 做下限保護。
年齡不影響目標值,它負責切換安全上限——
65 歲以上改成單次 150ml、每小時 800ml。
依據:衛福部、國健署(見 Reference)
下面這幾張都是程式跑起來直接抓的。




系統架構或流程圖
系統透過 pywebview 開啟一般桌面視窗,直接載入本機的 HTML、CSS 與 JavaScript, 再將 Python 函式提供給 JavaScript 呼叫。因此整體架構不需要經過 HTTP, 也不必設定連線字串,更沒有額外的後端服務需要部署。 對使用者來說,它就是一個可以直接開啟使用的桌面程式; 對開發端來說,則保留了網頁介面的彈性與 Python 的處理能力。
ADR(Architecture Decision Record)不只記錄最後採用的方案, 更說明為什麼沒有選擇看起來更直覺的做法。例如: 為什麼以「喝水次數」而不是「喝水總量」作為獎勵依據、 為什麼不採用常駐背景服務,以及為什麼資料庫要放在執行檔旁而非暫存目錄。 透過完整記錄決策背景、替代方案與取捨理由,即使日後回頭維護, 也能快速理解每項設計背後的思考脈絡。
如果改成「看今天喝夠沒」,一次灌 2000ml 就能把整座菜園澆完。 綁在次數上,遊戲進度才會跟著規律走。
不養一個常駐背景服務。開程式時拿每一株的
last_watered_at 跟現在比就好。
反正只有開程式才看得到菜園,結果一樣但單純很多。
PyInstaller 會把程式解壓到 sys._MEIPASS,那是暫存區。
改用 sys.executable 所在的目錄,資料就穩穩留著。
這是實際打包測試時發現的。
使用的 Package
資料庫用 Python 內建的 sqlite3,日期、JSON、執行緒也都是標準庫。
拿給別人跑,環境很好裝。
開一般的視窗把本機 HTML 讀進來,再把 Python 的函式給 JavaScript 呼叫。 選它是因為畫面可以用熟悉的 HTML/CSS 寫,又不必像 Electron 那樣包一整個瀏覽器進去。
只用到 pygame.mixer 一個模組,讓背景音樂獨立於畫面之外,
換頁也不會斷掉。電腦沒有音效裝置時它會安靜略過,其他功能照常。
打包成一個 exe(43.9 MB),不用安裝,點兩下就開。
datas 會把整個 web/ 收進去,之後加圖檔也不用改設定。
| 素材 | 來源 | 授權 |
|---|---|---|
| 作物插畫(24 種 + 2 張成長階段共用圖) | OpenMoji | CC BY-SA 4.0 |
| 介面字型 | jf open 粉圓體 | SIL OFL 1.1 |
| 背景音樂與四個動作音效 | Pixabay | Pixabay Content License |
| 飲水量計算依據 | 衛生福利部國民健康署 | 公開衛教資料 |
| 作物分級的市價依據 | 農業部「當季好蔬果」 | 公開統計資料 |
目前成果
這個專案我最想講的是這一段。有些機制細節操作一次看不出來, 要跨好幾天、或特定設定組合才會顯現——這正是自動化測試最派得上用場的地方。
garden_logic.py · calculate_next_streak()
連續天數是頂階作物的解鎖門檻,所以它得真的代表「每天都有來」。 關鍵是那一個判斷:上次澆水是不是昨天。
補上這個判斷之後,中斷幾天再回來就會重新起算, 「連續 14 天」這個門檻才名副其實,ADR-0002 想守的規律性也就守住了。
同時把這段邏輯從 water_slot() 裡抽出來寫成純函式,
跨月、跨年、閏年 2028-02-29 都能直接測,不必先偽造一整個資料庫狀態。
garden_logic.py · _get_wither_limit_minutes()
枯萎時限是「提醒間隔 × 每級的寬限倍率」,再壓一個絕對上限。 階級越高越嚴格:倍率 ×3 / ×2.5 / ×2 / ×1.5,上限 240 / 180 / 120 / 90 分鐘。
這裡再加一層下限保護,讓時限永遠不低於一個完整的提醒間隔。 提醒間隔設 150 分鐘時,頂階作物就從 min(150×1.5, 90) = 90 變成 max(90, 150) = 150 分鐘。
這樣一來,不論提醒間隔怎麼設定,程式一定會先提醒你,你也一定來得及照顧它。
max(min(間隔 × 倍率, 上限), 間隔)——一行就守住了。
這個專案有個習慣:踩到什麼就順手寫進註解, 連當初為什麼會這樣、後來怎麼處理都留著。以後回來看就不用重新推理一次。
db.py
PyInstaller 解壓的 sys._MEIPASS 是暫存區,改用 sys.executable 的目錄。
db.py
新苗的 last_watered_date 留空,這樣它不會被當成「今天已經澆過」。
db.py
連同當天澆過的紀錄一起清乾淨,配額就不會算成負數。
main.py
澆完水先不關視窗,等訊息看完再由前端收掉。
main.py
每一格都帶上 stages,畫面就能完整顯示「第 N / M 階段」。
枯萎時限的特性跟階級與間隔都有關,所以直接把 4 個階級 × 13 種提醒間隔,共 52 組全部跑一遍, 而不是挑幾個「看起來有代表性」的數字。窮舉才不會剛好跳過某個組合。
測試寫完之後,把兩段舊邏輯還原回去重跑, 確認真的會有 12 個測試亮紅燈,再改回來全綠。 這樣才知道這份測試真的在做事。
跑一次全部測試
> python -m pytest
148 passed in 0.25s
未來改進方向
桌面版已經把核心玩法跑順了,接下來想讓它在更多情境下也好用。
現在的提醒是程式自建的視窗。改成系統原生的 Toast Notification 之後, 程式最小化的時候也能準時提醒,更貼近「坐在電腦前」的使用情境。
現在 148 個測試涵蓋的是不碰資料庫的純函式。
接著想用 pytest fixture 搭配記憶體型 SQLite,
讓 water_slot()、plant_crop() 也能自動測。
字級可調、鍵盤操作支援。靜音鈕已經從「雙擊喇叭」改成看得見的按鈕—— 這種「功能在、但不容易被發現」的地方,是接下來要優先檢查的類型。
現在作物是一階一張圖。想加上季節外觀與隨機事件, 讓「照顧」這件事有更多可以看、可以期待的變化。
Reference
喝水量的每一個係數都附得上官方衛教出處,作物分級也查得到公開的菜價資料。
這個程式算出來的喝水量供日常參考。每個人實際需要多少, 會因身體狀況、天氣、有無疾病而不同。如有腎臟或心血管方面的疾病, 或其他特殊狀況,請先諮詢醫師再調整。
THANKS FOR WATCHING 賴子渝 JOE LAI