# Transfer Time Data v1

`TransferTimeData.pdb` はPalm Database形式の単一recordデータベースである。

- Database name: `Transfer Time Data`
- Type: `DATA`
- Creator: `TTok`
- Database version: `1`
- Multi-byte integer byte order: big endian
- Payload magic: `TTT1`

## Payload header

| Offset | Size | Field |
|---:|---:|---|
| 0 | 4 | ASCII `TTT1` |
| 4 | 1 | format version `1` |
| 5 | 1 | route count、`1..15` |
| 6 | 1 | holiday count、`0..96` |
| 7 | 1 | provider mask: ODPT `0x01`, CSV `0x02`, GTFS `0x04`, JR East web timetable `0x08`, Tokyo Metro public PDF `0x10` |
| 8 | 4 | generated time、Palm epoch seconds |
| 12 | 2 | timezone offset minutes、v1は `540` |
| 14 | 2 | header size、`24` |
| 16 | 4 | timetable/holiday coverage start、`YYYYMMDD` |
| 20 | 4 | timetable/holiday coverage end、`YYYYMMDD` |

header直後に、昇順かつ一意な `holiday count` 個の `uint32 YYYYMMDD` が続く。
coverageは祝日CSVだけでなく、登録した全routeの有効期間の共通部分である。Updaterは
生成日の前日より前を切り捨て、GTFS `feed_info` / calendarやSpecific Calendarの
有効期間終了後までbaseダイヤを延長しない。現在の東京日付を含まない場合は生成を拒否する。

## Route block

祝日一覧の後へ、route count個の可変長blockを連続して置く。

| Offset | Size | Field |
|---:|---:|---|
| 0 | 4 | ASCII `TTR1` |
| 4 | 1 | route version `1` |
| 5 | 1 | mode: rail `1`, bus `2`, CSV/other `3` |
| 6 | 1 | policy flags: bit 0はpersonal-only、bit 1はODPT Challenge由来 |
| 7 | 1 | day mask: weekday `1`, saturday `2`, holiday `4` |
| 8 | 2 | weekday departure count、`0..384` |
| 10 | 2 | saturday departure count、`0..384` |
| 12 | 2 | holiday departure count、`0..384` |
| 14 | 1 | special profile count、`0..8` |
| 15 | 1 | exception date count、`0..96` |
| 16 | 24 | operator、CP932 NUL終端、zero padding |
| 40 | 24 | line / bus route、CP932 NUL終端、zero padding |
| 64 | 24 | station / bus stop、CP932 NUL終端、zero padding |
| 88 | 24 | direction、CP932 NUL終端、zero padding |
| 112 | 16 | source label、printable ASCII NUL終端、zero padding |

公式公開PDFから取得した東京メトロrouteのsource labelは `TokyoMetroPDF` で始め、
provider maskの `0x10` に対応させる。

128-byte prefix直後にweekday、saturday、holidayの順で発車時刻を置く。
各発車時刻はサービス日0時からの分を表す `uint16` で、範囲は `0..1799`
（`00:00..29:59`）。各配列は厳密昇順である。

続いて `special profile count` 個の専用ダイヤを置く。各profileは次の可変長形式で、
Specific Calendarなど複数の特定日から共有できる。

```
departure_count:uint16
reserved:uint16 = 0
departures:uint16[departure_count]
```

通常3曜日と全special profileを合算したPDB全体の発車件数は24576件以下とする。
Palm側は実際の件数分だけ動的RAMを確保し、固定長の最大配列は確保しない。
同一内容のrouteも別indexとして順番どおり収録し、その発車件数は各route分を合算する。

最後に `exception date count` 個の8-byte date mapを置く。

| Offset | Size | Field |
|---:|---:|---|
| 0 | 4 | date、`YYYYMMDD` |
| 4 | 1 | profile index。`0` は運休、`1..special_profile_count` は専用ダイヤ |
| 5 | 3 | reserved、zero |

date mapは日付の昇順かつ一意とする。該当日が存在する場合は、通常の平日・土曜・
日曜祝日判定を行わず、指定された専用profileで完全に置換する。これによりODPTの
Specific Calendarや事業者固有の臨時ダイヤを表現する。

Challenge由来を示すbit 1は、公開可否を示すbit 0とは独立して保存する。Palm側は
現在日がChallenge利用期限の2027-03-14を超えた場合、そのrouteを運行0件として扱う。
Windows Updaterも期限後はChallenge bitを含む既存outputを削除し、期限エラーを返す。

最後のroute block終端はpayload終端と完全一致しなければならない。readerはmagic、
version、正確な長さ、日付、provider mask、day mask、文字列終端とpadding、時刻範囲、
時刻順、profile参照範囲をすべて検証し、一つでも不正ならpayload全体を拒否する。
