init: Redis-backed Pokémon 雷達 API

- radar_fetcher.py:呼叫 Function Server 抓 twpkinfo.com 資料後寫入 Redis (TTL 300s)
- pokemon_radar_api.py:FastAPI /scan,從 Redis 讀取並依 request 即時二次篩選;Redis 不可用時回 200 空結果,不再 500
- pokemon_location_fetcher.py:舊版 CLI,仍由 fetch_and_upload.sh 使用
- 文件:README (參考手冊)、QUICKSTART (操作指南)、SUMMARY (故事線)、CLAUDE.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-20 09:13:59 +08:00
commit f7ef105436
18 changed files with 2919 additions and 0 deletions

50
pokemon_radar_example.py Normal file
View File

@@ -0,0 +1,50 @@
from pokemon_location_fetcher import PokemonRadarClient
import json
# ===== 你可調的參數 =====
LAT, LNG, ZOOM = 25.0478, 121.5170, 12
STATE_PATH = "state.json"
UA_FROM_STATE = True
SHOT = True
# 篩選參數(先保守,不加過度嚴格的條件)
MIN_REMAINING = 300
MIN_IV = None # ex: 90
PERFECT_ONLY = True # 只要 100% IV
SPECIES = "" # ex: "133,669,伊布"
# ===== 開始跑 =====
client = PokemonRadarClient() # 可改 url/token/script如有需要
payload = client.fetch(LAT, LNG, zoom=ZOOM, shot=SHOT, state=STATE_PATH, ua_from_state=UA_FROM_STATE)
items_raw = payload["items"]
debug = payload.get("debug", {})
print("----- debug notes -----")
for n in debug.get("notes", []):
print(n)
print("-----------------------")
print(f"📦 Raw items: {len(items_raw)}")
# 先把「未過濾」的也存一份,方便你比對
with open("pokemon_data_raw.json", "w", encoding="utf-8") as f:
json.dump({"items": items_raw, "debug": debug}, f, ensure_ascii=False, indent=2)
print("💾 Saved raw JSON to pokemon_data_raw.json")
# 看一下前 3 筆
for i, it in enumerate(items_raw[:3], 1):
print(f"[raw #{i}] id={it.get('id')} name={it.get('name')} iv%={it.get('iv_pct')} rem={it.get('remaining')}")
# 套用篩選
items = client.postprocess(
items_raw,
min_remaining=MIN_REMAINING,
min_iv=MIN_IV,
perfect_only=PERFECT_ONLY,
species=SPECIES,
)
print(f"🔎 Filtered items: {len(items)} "
f"(min_remaining={MIN_REMAINING}, min_iv={MIN_IV}, perfect_only={PERFECT_ONLY}, species='{SPECIES}')")
# 存「已過濾」版本(固定檔名)
client.save(items, debug, payload.get("screenshot"))