Skip to main content

Terminal split-flap (Solari) departure board for JR / Tokyo Metro / Toei lines.

Project description

🚉 JR / Tokyo Metro Split-Flap Board

English · 繁體中文 · 日本語

終端機裡的 JR/東京地鐵 翻牌式(split-flap / Solari board)時刻表站牌模擬器。

每次刷新會先像老火車站、航站樓的機械翻牌那樣亂數翻滾,再逐格鎖定成真實的到站資訊。 20 條路線、資料驅動、可接 ODPT 即時資料,並提供可嵌入 Claude Code 狀態列的單行跑馬燈模式。

demo

+----------------------------------------------------------+
|   JY   山手線  Yamanote Line                             |
|   JY 17                     新  宿                       |
|                  しんじゅく   Shinjuku                   |
|  ◀ 新大久保                ■                   代々木 ▶  |
|  < Shin-Okubo           Shinjuku               Yoyogi >  |
+----------------------------------------------------------+
| 時刻   | 種別       | 行先 (方面)                | 番線  |
|----------------------------------------------------------|
| 15:45  | 各駅停車   | 品川・渋谷方面             | 1     |
| 15:45  | 各駅停車   | 上野・池袋方面             | 2     |
| 15:50  | 各駅停車   | 品川・渋谷方面             | 1     |
| ...    | ...        | ...                        | ...   |
|----------------------------------------------------------|
| Yamanote Line                                src: STATIC |
+----------------------------------------------------------+

終端機實際輸出帶有各線的官方代表色(山手線綠、銀座線橘、丸ノ内線紅⋯⋯)。


✨ 功能

  • 真實資料:可接 ODPT(公共交通開放資料平台)即時時刻表;未設定金鑰時自動回退到內建的真實靜態時刻表。站牌右下角誠實標示資料來源 src: ODPT / src: STATIC
  • 20 條路線可切換,全部資料驅動(見下方路線表)。
  • 翻牌動畫:經典 split-flap / Solari board 效果,速度可調。
  • 單行跑馬燈模式:站名釘住、班次捲動,可嵌入 Claude Code 狀態列。
  • CJK 對齊:以 east_asian_width 處理日文全形字佔 2 格的問題,每行精準對齊到固定視覺寬度。

🚀 快速開始

# (選用)只有要接 ODPT 即時資料時才需要
pip install requests

# 列出全部 20 條路線與站點
python3 main.py --list

# 全站牌 + 翻牌動畫(預設山手線新宿,每 10 秒刷新;Ctrl-C 結束)
python3 main.py

--station 接受英文名、站號或站 id,大小寫不拘(例:--station shinjuku--station 17--station JY17)。

# 指定路線/站點,渲染一次就結束
python3 main.py --once --line ginza        --station ginza
python3 main.py --once --line keihintohoku --station tokyo --no-flap

# 翻牌速度微調
python3 main.py --line yamanote --station shinjuku --flap-delay 0.15   # 更慢、更機械感
python3 main.py --line yamanote --station shinjuku --flap-steps 8      # 更少格、更俐落

# 單行跑馬燈
python3 main.py --mode statusline --line oedo --station tochomae --columns 70
python3 main.py --mode statusline --line marunouchi --station tokyo --columns 70 --scroll-all

🧩 更多模式:TUI、番茄鐘、通勤守門員、行事曆

除了站牌與跑馬燈,同一支 CLI 還提供四種附加模式(所有舊旗標行為不變,這些都是選用)。

# 互動式 curses 瀏覽器:左邊是「依城市分組」的路線清單(各線官方色,
# j/k 移動、/ 模糊搜尋、h/l 切換站點、f 收藏、q 離開),右邊是即時彩色站牌
# (切換線/站時會播翻牌動畫)
python3 main.py --tui

# 番茄鐘=一趟電車旅程:把專注計時畫成從起點到終點的乘車。會在路線上
# 自動挑兩站(或用 --from/--to 指定),先播翻牌動畫,之後每秒重繪,
# 直到「とうちゃく」(抵達)。
python3 main.py --pomodoro 25 --line yamanote
python3 main.py --pomodoro 25 --line yamanote --from shinjuku --to tokyo
python3 main.py --pomodoro 1 --line yamanote --once   # 只畫一格就結束

# 通勤守門員:「我幾點要出門才趕得上下一班車?」需要在設定檔填
# [commute] home/work(見下)。早上 → 家→公司,下午/晚上 → 公司→家。
python3 main.py --commute                       # 完整站牌
python3 main.py --commute --mode statusline     # 精簡單行

# 行事曆來源:用本機 .ics 檔當作發車來源(標籤 AGENDA),把接下來的
# 會議當成電車顯示,而非時刻表。
python3 main.py --feed-ics ~/cal.ics --once
python3 main.py --feed-ics ~/cal.ics --mode statusline --columns 70

設定檔

設定讀自 ~/.config/jrboard/config.toml(會尊重 XDG_CONFIG_HOME)。檔案缺失或格式錯誤會直接忽略——一律套用預設值,而 CLI 旗標永遠覆寫設定檔。

[board]
line = "oedo"
station = "tochomae"
columns = 50
width = 60
flap_steps = 22
flap_delay = 0.08

[commute]
home = ["yamanote", "shinjuku"]
work = ["yamanote", "tokyo"]
leave_buffer_min = 7      # 走到車站的緩衝分鐘數

在 TUI 中切換的收藏會存到 ~/.config/jrboard/favorites.txt(每行一組 line_key,station_key)。

安裝/進入點

pip install -e .        # 安裝 `jrboard` 命令列腳本
jrboard --list          # 與 `python3 main.py` 相同的 CLI
jrboard --tui

🚇 路線一覽(20 條)

代碼 --line key 路線 站數 範例站
JY yamanote 山手線(環狀) 30 shinjuku
JC chuo 中央線快速 24 tokyo
JB sobu 中央・総武線各駅停車 39 akihabara
JK keihintohoku 京浜東北・根岸線 47 tokyo
JA saikyo 埼京線 19 osaki
JS shonanshinjuku 湘南新宿ライン 19 shinjuku
JO yokosuka 横須賀線 19 yokohama
G ginza 東京メトロ銀座線 19 ginza
M marunouchi 東京メトロ丸ノ内線 25 tokyo
H hibiya 東京メトロ日比谷線 22 naka-meguro
T tozai 東京メトロ東西線 23 otemachi
C chiyoda 東京メトロ千代田線 19 yoyogi-uehara
Y yurakucho 東京メトロ有楽町線 24 wakoshi
Z hanzomon 東京メトロ半蔵門線 14 shibuya
N namboku 東京メトロ南北線 19 meguro
F fukutoshin 東京メトロ副都心線 16 wakoshi
A asakusa 都営浅草線 20 asakusa
I mita 都営三田線 27 meguro
S shinjuku 都営新宿線 21 shinjuku
E oedo 都営大江戸線 39 tochomae

--line shinjuku 指的是都營新宿線(地鐵);JR 線各有獨立 key(chuo/sobu/…)。

🌏 其他城市(京都/大阪/札幌/小樽)

--city 篩選城市:python3 main.py --list --city Osaka--rotate --city Osaka 只在大阪境內隨機巡迴。

key 城市 路線 站數
osaka-loop 大阪 JR 大阪環狀線(環狀) 19
osaka-midosuji 大阪 御堂筋線 20
osaka-tanimachi 大阪 谷町線 26
kyoto-karasuma 京都 地下鐵烏丸線 15
kyoto-tozai 京都 地下鐵東西線 17
kyoto-randen 京都 嵐電 嵐山本線(路面電車) 13
kyoto-sagano 京都 JR 嵯峨野線(山陰本線) 15
kyoto-keihan 京都 京阪本線 42
sapporo-namboku 札幌 南北線 16
sapporo-tozai 札幌 東西線 19
sapporo-toho 札幌 東豊線 14
otaru-hakodate 小樽 JR 函館本線(小樽—札幌) 15

🛰️ 接 ODPT 即時資料

  1. https://developer.odpt.org/ 免費申請 consumer key。
  2. 設環境變數後執行:
export ODPT_KEY="你的金鑰"
python3 main.py --line yamanote --station shinjuku   # 站牌右下角會顯示 src: ODPT

抓不到(無金鑰、API 錯誤、空資料)時會自動回退靜態時刻表並在 stderr 記錄原因,站牌顯示 src: STATIC

🔐 金鑰請勿寫進程式或 commit,用環境變數即可(.env 已被 .gitignore 忽略)。


📟 接進 Claude Code 狀態列(statusLine)

多行站牌不適合狀態列(會佔 16 行),請用單行 statusline 模式。它會把站名釘在最左、班次像燈條捲過去:

[JY] 17 新宿 ▸ 15:45 品川・渋谷方面  15:45 上野・池袋方面  15:50 …

~/.claude/settings.json

{
  "statusLine": {
    "type": "command",
    "command": "python3 /Users/minghsuan/Downloads/JR-timetable/main.py --mode statusline --line yamanote --station shinjuku --columns 80"
  }
}

兩個狀態列的本質限制(已在設計內處理):

  1. 非 TTY:statusLine 指令沒有終端寬度,必須用 --columns N 明確給寬度,跑馬燈才會捲動。
  2. 非計時器驅動:Claude Code 只在 render(有活動)時才重跑指令,所以跑馬燈是「每次刷新前進一格」而非閒置時平滑流動。捲動偏移量由當前時間推導,因此每次刷新位置都不同。

--scroll-all 可改成整行一起捲動(連站名一起跑)。

用 csl 主題(推薦,會動的跑馬燈)

若你用 csl 狀態列主題管理器,本專案附了一個現成主題 integrations/csl/jr-board.sh(+ manifest)。它覆寫 render() 呼叫上面的跑馬燈,並靠 settings.jsonrefreshInterval: 1 達成每秒前進一格的真實捲動

# 安裝主題到 user-tier 後啟用
cp integrations/csl/jr-board.* ~/.config/csl/themes/
csl preview jr-board     # 先試跑一次
csl set jr-board         # 啟用(自動改寫 settings.json 並備份)
csl set bastille-day     # 隨時切回原本的主題

jr-board.sh 頂部可調 JR_LINE / JR_STATION / JR_COLUMNS(越窄越會捲)/ JR_SCROLL_ALL


🎞️ 翻牌動畫調校

旗標 預設 效果
--no-flap 跳過動畫,直接畫出結果
--flap-steps N 22 從全亂到解出的影格數;越大越漸進
--flap-delay S 0.08 每影格停留秒數;越大越慢

預設整段動畫約 2 秒。動畫「以什麼順序鎖定」由 jrboard/flap.pylock_threshold() 決定(目前是由左往右擦除+微抖動),想改成隨機落定或 ease-out 收尾,調這個函式即可,其他模組不用動。


🏗️ 架構

資料驅動:引擎與路線無關,新增路線 = 在 jrboard/data/ 丟一個 <key>.json,不必改任何程式

模組 職責
jrboard/width.py CJK 全形字 / ANSI 視覺寬度計算與對齊
jrboard/model.py Line / Station 資料模型,載入 data/*.json
jrboard/sources.py 時刻表來源(ODPT + 靜態備援,repository pattern)
jrboard/flap.py split-flap 翻牌動畫引擎(純函式、可測)
jrboard/render.py 站牌 + 時刻表 ANSI 渲染
jrboard/statusline.py 單行跑馬燈
jrboard/cli.py argparse CLI 與刷新排程
jrboard/data/*.json 各路線的站點 + 時刻表資料

新增一條路線

jrboard/data/ 放一個 <key>.json,照既有檔的結構填:

{
  "key": "tokaido",
  "name_jp": "東海道線", "name_en": "Tokaido Line",
  "symbol": "JT",
  "color": { "name": "...", "ansi_fg": "",
             "ansi_bg": "", "hex": "#F68B1E" },
  "operator": "JR-East",
  "odpt_railway": "odpt.Railway:JR-East.Tokaido",
  "loop": false,
  "stations": [
    { "id": "JT01", "number": "01", "name_jp": "東京", "kana": "とうきょう",
      "name_en": "Tokyo", "odpt_station": "odpt.Station:JR-East.Tokaido.Tokyo" }
  ],
  "timetable": {
    "first_train": "04:30", "last_train": "00:30",
    "headway_min": { "weekday": { "7": 5, "8": 4, "...": 0 }, "holiday": { "...": 0 } },
    "directions": [
      { "id": "down", "name_jp": "熱海方面", "via_jp": "横浜方面", "track": "1" },
      { "id": "up",   "name_jp": "東京方面", "via_jp": "品川方面", "track": "2" }
    ]
  }
}

存檔後 python3 main.py --list 立刻就會出現這條線。


✅ 測試

python3 -m pytest tests -q      # 47 tests

涵蓋:視覺寬度(CJK+ANSI)、資料模型(載入/找站/環狀鄰站)、時刻表來源(靜態產生與 ODPT 備援切換)、翻牌(寬度保持、最後一幀完全解出)、狀態列(站名釘住、跑馬燈隨時間前進)。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tokyo_train_board-0.1.0.tar.gz (102.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tokyo_train_board-0.1.0-py3-none-any.whl (109.5 kB view details)

Uploaded Python 3

File details

Details for the file tokyo_train_board-0.1.0.tar.gz.

File metadata

  • Download URL: tokyo_train_board-0.1.0.tar.gz
  • Upload date:
  • Size: 102.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.8

File hashes

Hashes for tokyo_train_board-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dafd142e7692ee2766f7e21ad5facdae3be15b94d504c43d2b2fafd871bb06ed
MD5 5ba92b8fff08a4e021a0135232e48676
BLAKE2b-256 bb71bf53b77685f2c3ba2c0187097b3a6d533ef3512ad198a62e07e6bcf45f95

See more details on using hashes here.

File details

Details for the file tokyo_train_board-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for tokyo_train_board-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cf72c08d26f006b76816f9e19d095a421ed34a23cbaa08a71538cd0e6d6d669b
MD5 9c63b84597095f6d8922fc6449dd28e8
BLAKE2b-256 88f743dc876ebd6d3f2efa2bb181540c9a8140e58eea97fceeb89aea0bfbb052

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page