想做到的事
- 讓「分次慢慢喝」比「一次喝很多」划算
- 喝水量的建議都查得到官方出處,不自己亂編公式
- 整支程式離線跑,健康資料只留在自己電腦裡
- 程式關掉的期間,該枯萎的還是會枯萎
動機與目標
市面上的喝水提醒 App 幾乎都是同一套做法:設個間隔、跳通知、按「已喝水」。 我自己載過幾個,最後都一樣,通知變成隨手滑掉的東西。 因為不理它也不會怎樣,那個按鈕按不按其實沒差。
會痛的提醒才有用。
所以這個專案想做的事很單純:讓「沒喝水」真的有一個看得到、 而且會愈來愈糟的後果。菜園剛好很適合,作物會枯萎, 而且是自己害死的,救不回來。
功能介紹
整套玩法就靠一條規則撐起來,其他設計都是為了讓這條規則站得住腳。
這裡跑的就是 garden_logic.py 那套規則。
拉一下滑桿,看同樣的水量、兩種喝法會差多少。
一次算 250ml,總共 1500 ml
一樣喝 1500 ml,但只分 1 次喝完
可澆 6 株
可澆 1 株
分在哪一級會影響三件事:要連續幾天才解鎖、要澆幾次才長大、收成拿多少金幣。 價錢是查農業部「當季好蔬果」來的,不是憑感覺排。
橫條的長度就是那一級的價錢範圍,四條共用同一把 0–1031 元的尺。 頂階的櫻桃一公斤 1031 元,初階的紅蘿蔔 28 元,差了快 37 倍。 差這麼多,所以頂階要連續 14 天才給解鎖。
下面這幾張都是程式跑起來直接抓的,不是設計稿。




系統架構或流程圖
pywebview 會開一個一般的視窗,把本機的 HTML 讀進來, 然後把 Python 的函式直接給 JavaScript 叫。 不用 HTTP、不用設連線字串,也沒有後端要架。
每一份都寫清楚「為什麼不用那個看起來比較直覺的做法」, 免得以後自己好心把它改回去。
如果改成「看今天喝夠沒」,那一次灌 2000ml 就能把整座菜園澆完, 而這剛好就是最該防的喝法,遊戲跟健康目標就脫鉤了。
不養一個在背景一直跑的服務。開程式的時候,拿每一株的
last_watered_at 跟現在比,超過時限就算它枯了。
反正只有開程式才看得到菜園,結果一樣但簡單很多。
PyInstaller 會把程式解壓到 sys._MEIPASS,程式一關就清空。
資料庫放那裡等於每次重開都忘記你是誰。這是真的踩過才知道的,
不是先想到的。
使用的 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 |
| 飲水量計算依據 | 衛生福利部國民健康署 | 公開衛教資料 |
| 作物分級的市價依據 | 農業部「當季好蔬果」 | 公開統計資料 |
目前成果
這個專案我最想講的不是做了幾個功能,而是這兩個 bug。 它們的共同點是你操作一次根本看不出來,所以手動點來點去永遠測不到。
garden_logic.py · calculate_next_streak()
原本只看「上次澆水那天不是今天」,完全沒去確認是不是昨天。 所以中斷三個月再回來澆一次,連續天數照樣加一。
照這樣算,一個月只開一次程式,14 個月就能解鎖要「連續 14 天」的頂階作物。 這樣哪裡叫規律?ADR-0002 最想守的那件事就這樣被繞過去了。
garden_logic.py · _get_wither_limit_minutes()
枯萎時限是「提醒間隔 × 每級的寬限倍率」,然後再壓一個絕對上限。 問題是那個上限沒有再加一層下限保護。
提醒間隔設 150 分鐘的話,頂階作物算出來是 min(150×1.5, 90) = 90 分鐘, 比提醒間隔本身還短。也就是程式還沒提醒你,菜就已經死了。
而枯萎會讓連續天數歸零,所以就變成 解鎖頂階 → 種下去 → 一定枯萎 → 資格又沒了,繞不出來。
第二個 bug 只有在特定組合才會出現,階級越高、間隔越長才踩得到。 所以枯萎時限是把 4 個階級 × 13 種提醒間隔,總共 52 組全部跑過, 不是挑幾個「看起來有代表性」的數字試試看。
測試寫完之後,我把那兩個 bug 故意改回原本的錯誤寫法, 確認真的會有 12 個測試變紅。 如果把程式改壞了測試還是全綠,那這份測試根本沒在做事。
跑一次全部測試
> python -m pytest
148 passed in 0.19s
未來改進方向
桌面版已經證明這套玩法行得通,接下來要處理的是「只能在自己那台電腦種菜」這件事。 雲端的幾個主要部分都寫好也試過可以跑,這是接著要走的方向。
規則引擎(Cloudflare Workers + D1)已經寫好也試過可以跑。 接下來要把桌面版的 SQLite 跟雲端的資料表接起來, 這樣同一座菜園在電腦跟手機上看到的就會一樣。
桌面版最強的地方是坐在電腦前的時候會準時叫你, 但一離開座位就沒用了。加上 Web Push 之後, 離開電腦的那段時間也能接著提醒,兩邊剛好補起來。
現在這 148 個測試都是在測不碰資料庫的函式。
會動到資料庫的(water_slot、plant_crop)
跟畫面上的操作,目前還靠一份約 500 項的清單手動點,這部分想改成自動跑。
現在作物就是換四張圖,一階一張。 想加天氣、不同季節的樣子,還有蟲害之類的事件, 讓「照顧」這件事有更多東西可以看。
Reference 或參考資料
喝水量的每一個係數都查得到官方衛教出處,作物分級也查得到公開的菜價資料。
這個程式算出來的喝水量只是給日常參考用的。每個人實際需要多少, 會因為身體狀況、天氣、有沒有生病而不一樣。如果有腎臟或心血管方面的疾病, 或是其他特殊狀況,請先問過醫生再調整。