§
------------------------------------------------
TTT - Simutrans 簡易タイムテーブル機能パッチ

				Jul 13, 2012
				 for TTT-039
				    wackdone
------------------------------------------------

Simutransで、列車の等間隔運行や調整された退避などを実現するための
機能追加パッチです。

列車のスケジュール上で、駅間の運行計画時間や始点での予定出発時刻を
指定することで、計画した時刻表にできるだけ沿って運行させるようにできます。

ただし「できるだけ」の運用なので、計画に対して充分な評定速度が出せていない
場合や、その他さまざまな要因で列車に遅延が出ることもあります。
遅延が出ている場合は、駅の停車時間を短くすることで回復運転を試みます。

鉄道以外の乗り物にも使用可能ですが、テストは鉄道とバスでしかしていません。
また以下、乗り物全般を指す意味で「列車」と呼びます。


--------------------
= バージョン情報
--------------------
パッチバージョン: TTT Version 0.39
対応Simutransソース: Nightly r5788
パッチファイル名: simutrans-r5788-ttt-039.patch

== 適用可能ソースについて
手元では、Release 111.3 (r5772) にも適用できる
(ただし、simversion.h だけは手であてる必要あり)、
そして動作することを確認しています。
おそらく、この間のバージョンであればどれも適用可能でしょう。

なお最新(2012.7.5時点)の r5804 へ適用可能かどうかは未確認です。
(試してご報告をいただけると助かります。)


--------------------
= セーブファイルのバージョン
--------------------
本パッチを適用すると、ゲームのセーブファイルのバージョン番号が
  0.112.5
になります。
(最近のリリースである 111 よりもある程度余裕をもってこの値にしています。)

0.111.4 以前のセーブファイルをロードする事は可能ですが、
これをこのパッチのあたったSimutransでセーブすると、
セーブファイルバージョンが 0.112.5 になってしまいます。
よって、オリジナル Simutrans ではロードできないものとなります。

またこの値は近い将来 Simutrans本家で使われる可能性が高く、
その際にはロード時に想定外のクラッシュが発生します。
Simutransが 112 になる前にこのパッチが本家へマージされることを願っていてください。

なお互換性維持のため、このパッチで一時的に使用していた 0.811.5 という
番号のファイルもロードは可能です。


--------------------
= パッチの適用とビルド
--------------------
Simutransのビルドが可能な環境とスキルがあることを前提に説明します。

== パッチの適用
Nightlyのソースを入手し、これに対して同梱のパッチファイル
  simutrans-r5788-ttt-039.patch
をpatchコマンドなどを使ってあててください。

例:
{{{
  svn co -r5788 svn://tron.homeunix.org/simutrans/simutrans/trunk
  cd r5788
  patch -p0 < simutrans-r5788-ttt-039.patch
}}}

== コンフィグ
ビルドコンフィグファイル (config.defaultなど) の中に以下の行を追加してください。

{{{
  CFLAGS += -DSCHEDULE_TIMETABLE
}}}

なおソースコード上は全てこれを元にifdefで制御されており、
このマクロ定義をしなければ、動作がオリジナル通りになります。
障害時にはこの定義を切り替えて動作を比較してください。

また実験的に提供している機能を有効にするために、以下のそれぞれの指定を
加えることができます。

車両ツールチップ表示機能: マウスオーバなどで表示されます
{{{
  CFLAGS += -DSCHEDULE_TIMETABLE_CONVOITIP
}}}

時間情報表示バー: 乗物の情報ウィンドウに表示されます
{{{
  CFLAGS += -DSCHEDULE_TIMETABLE_TIMINGBAR
}}}

時刻表ウィンドウ機能: 路線管理ウィンドウの中のボタンから開くことができます
{{{
  CFLAGS += -DSCHEDULE_TIMETABLE_TTV
  SCHEDULE_TIMETABLE_TTV = 1
}}}

== ビルド
オリジナルと同様に make でコンパイル/リンクできます。

== 言語翻訳ファイルへの追記
仮の翻訳ファイルとして、
  TTT.ja.tab
を同梱しています。
text/ja.tab の後に追加してご使用ください。

翻訳の大部分は、日本語フォーラム上で moka様に作成していただきました。
ありがとうございます。
ただし、全ての翻訳がされているわけではありません。
また用語の統一が不十分なところもありますのでご了承ください。


--------------------
= 簡易タイムテーブル機能の概要
--------------------
簡易タイムテーブル機能は、列車の運行に時間面での制約をつける
二つ種類(相対時間ベースと絶対時間ベース)の運行機能から構成されます。
この二つは、それぞれ片方だけ使用することもできますし、
組み合わせて使用することもできます。
その組み合わせは路線ごとや列車ごとに選択することができます。

== 駅間所要時間の計画
列車や路線(line)のスケジュール設定上で、列車が
  前の駅を*出発して*から
  今の駅を*出発する*まで
の計画時間(目標値)を指定できます。
(出発から出発までというところがこの機能の肝です。)

これが指定された列車は、この計画時間をできるだけ守るようにしながら運行します。
もし遅れが出た場合にはその量を記憶しておいて、その先のスケジュールの中にある
余裕時間を使って遅れを解消しようとします。

この機能によって一つの列車を安定した駅間時間で走行させることができます。
全ての駅間に設定されていれば、この安定性は列車のスケジュール全体に有効であり、
駅間時間の合計を周期とした運転をいつまでも続けることが可能です。
オリジナルのSimutransで発生するような、積載重量や積み降ろし時間の変化による
運行時間の乱れの蓄積は起こりません。

適切に設定した上で、車庫からの出庫などのタイミングで列車同士の運行間隔を
手動で作っておけば、以後はその間隔を維持しながら運行します。

== 周期的な始点発時刻指定
始点駅(スケジュールの先頭の駅)では、列車の出発*時刻* (ゲーム内時間を
もとにしたタイミング) を指定して発車させることもできます。
時刻には周期と列車ごとのオフセットを指定することができます。
これを適切に設定することで、列車のスタート時の間隔を手動で調整する必要もなくなり、
さらに、同一線路を走る複数の路線にまたがって周期を揃えて設定することで、
周期性のある簡単なパターンダイヤを実現することができます。

またこのオフセットを路線内の全ての列車に自動設定させることもできます。

== 処理の軽さ
TTTの基本機能である
  * 駅間所要時間計画に沿った運行
  * 周期的な始点発時刻による運行
のそれぞれは、オリジナルのSimutransの処理に比べて、
ごくわずかな処理増加で済んでいます。

駅を出る時に行われる列車の経路探索などの重さに比べれば、
限りなく0に近いと言っても差し支えない範囲の増加です。

ただし、運行計画作成の時に使うユーティリティーツールである
時刻表ウィンドウ、またそこから使用できる始点発時刻の自動再設定機能などを
使用すると、動作が若干重めになります。
しかしこれらは、通常の運行が続いている間に長く使い続けるものではないので、
大きな問題にはならないと考えられます。

--------------------
= 駅間所要時間計画運行の仕組み
--------------------
スケジュールの中のそれぞれの駅には、前駅の出発から今駅の出発までの
計画スプリット時間 (planned) が設定できます。
(中継点にも設定できてしまいますが、現状では無視されます)

また各列車は、
  前駅の出発時刻 (last_departure)
  積算遅延時間 (delay)
を記憶しています。

早着や遅延が発生した場合には、積算遅延時間に繰り込みます。
列車はこの遅延時間がなるべくゼロになるように、
駅の出発時刻(go_on)を調整します。

アルゴリズムは簡単には以下のようになります。

  * 駅の停車時: 出発予定時刻の算出
    . 実績走行時間の計測: trip = now - last_departure
    . 出発予定時刻の計算: go_on = now + (planned - trip) - delay

  * 発車の判定
    . now が go_on 以上になったら発車処理
      (停車時点ですでに過ぎている場合はできるだけ早く発車しようとする)

  * 駅の発車時: 遅延時間の再計測
    . 実績駅発間時間の計測: elapsed = now - last_departure
    . 遅延時間の積算: delay += elapsed - planned
    . 発時刻の記録: last_departure = now

コード上では、これとは少し違う形の式になっていますが、
意味的には同じ計算を行っています。


== 運行の開始
last_departure は車庫を出る際に無効値に設定されます。
この直後の停車では、ここに示した出発予定時刻の計算は行われず、
Simutrans本来の「積載して出発」の時間で出発されます。
(この場合、delay も更新されません)

この出庫後の最初の停車でlast_departureが記録されますので、
以降の停車では出発予定時刻の計算と調整が行われるようになります。


== ジッタによる遅延の発生
シミュレーション全体の重さや、Simutransの入れる処理ディレイ(一部ではランダム)
などがあり、実際の列車の出発時刻を厳密に守ることはできません。
そのため、列車はほぼ常に若干遅延のまま運行します。

ですが、計画が適切に設定されている (駅間計画時間が列車の走行性能に対して余裕がある) 
状態であれば、遅延時間が積もって増大していくことはありません。

なお現在は、発車判定の時に使用する現在時刻に対してスラック
(TIMETABLE_SLACK == 1000ticks) を入れていますが、それでもだいたい遅延側に
振れてしまうようです。


--------------------
= 周期的始点発時刻計画の仕組み
--------------------
スケジュール (路線) に対してタイムテーブルの周期時間 (cycle) を指定する
(非0にする) と、始点(スケジュールの先頭)では、出発予定時刻の決定方法が変化します。

始点とはスケジュールの先頭の項目です。これは必ず駅(halt)でなければなりません。
(これが中継点(waypoint)の場合は、この機能は動作しません。)

それぞれの列車には始点発時刻のオフセット (offset) を指定できます。
これは始点を出発する時刻の列車ごとのずらし分です。

始点での出発予定時刻は以下のような条件を持ちます。
  go_on = N * cycle + offset    (ただしここで Nは非負の整数)
このようなNの中で、go_on がゲーム内の現在時刻 now 以上になる最小のNを選び、
この時の go_on を出発時刻とします。

つまり簡単に言えば、
  cycleごとに繰り返す時刻の上で、時刻がoffsetになった時に出発する
となります。

例:
  cycle=1000で、列車Aがoffset=0、列車Bがoffset=500だったら、
  nowを1000で割った余りが
      0 の時に列車Aが始点から出発
    500 の時に列車Bが始点から出発
  となります。

基準にしているnowはゲーム内の絶対時刻であるため、複数の種別があった場合でも
それらのcycleを揃えておけば、同一の周期内でパターン化して、offsetを指定できます。

例:
  cycle=1000で、普通Aがoffset=0, 普通Bがoffset=500, 優等Aがoffset=300だったら、
  nowを1000で割った余りが
      0 の時に普通Aが始点から出発
    300 の時に優等Aが始点から出発
    500 の時に普通Bが始点から出発
  となります。

一つの応用としては、片方の種別のcycleを、もう片方の種別のcycleの整数倍に
して使うこともできます。

例:
  優等のcycle_E=500, 普通のcycle_L=1000とした上で、
  優等Aが offset_Ea=250
  普通Aが offset_La=100, 普通Bが offset_Lb=700 であれば、
  nowを1000で割った余りが、
    100 の時に普通Aが始点から出発
    250 の時に優等Aが始点から出発
    700 の時に普通Bが始点から出発
    750 の時に優等Aが始点から出発
  となります。


--------------------
= 始点発時刻の自動均等設定
--------------------
路線(line)に対して出発時刻の間隔(pitch)を指定してトリガーをかけると、
路線に所属する全ての列車に対して自動的にoffsetを付与することができます。

この時、オフセットのずらし量(shift)も合わせて指定することができ、
これを利用すれば全ての列車のoffsetを一定量だけずらすといったこともできます。
また、運行障害などによってダイヤが大幅に乱れた場合などに、スジを落として
ダイヤ回復をさせる(編成の運用は変更される)のにも利用できます。

自動均等設定は以下のように行われます。

  トリガーがかかった後、最初に始点に到着した列車:
    shift + N * pitch が (now % cycle) を過ぎていてもっとも近い整数 N を選び、
   この値を offset に設定する。

  以降に指定に到着した列車:
    この前に設定した列車の offset に pitch を加える (mod cycle)

全ての列車にoffsetが設定できたら、自動均等設定が終了します。
(以降はoffsetは設定された値のまま運行を繰り返します)

例えば
  cycle = 1000
  pitch = 250
  shift = 20
で所属列車が4編成 (A, B, C, D)の時にトリガーがかかったとします。
列車は D, C, A, B の順番に線路上で走行しているとして:

  列車Cがトリガー後最初に始点に到着: この時の now=5680 だとすると
    周期内現時刻 5680%1000 は 680 であり、これに最も近い値を選ぶとn=3、つまり
    C.offset = shift+pitch*n = 20 + 250 * 3 = 770

  列車Aが始点に到着:
    A.offset = C.offset + 250 (mod cycle) = 20

  列車Bが始点に到着:
    B.offset = A.offset + 250 (mod cycle) = 270

  列車Dが始点に到着:
    D.offset = B.offset + 250 (mod cycle) = 520

これで一周分のoffsetが自動設定完了です。


== 継続的(Persistent)な自動均等設定
列車に対して自動均等設定をいつまでも繰り返させることも可能です。
この場合は各列車は始点に到着するたびに、
  (now % cycle) < shift + N * pitch
となる最小のNを毎回選んで、その都度、列車のoffsetを再設定します。

これを使用した運行は例えば
  「前後の列車とは関係なく毎時 M分に出発」
というような意味になります。

現在のバージョンでは、この設定は時刻表ウィンドウの中の
「運行アシスタント」の中からのみ行えます。


--------------------
= 時間の単位と最大値
--------------------
ゲーム内でのシミュレーション時間の単位と、
このパッチの機能でユーザに見える形で表現、入力する時間の単位は異っています。
これは、ゲームデータ量の節約とユーザに数値を扱いやすくさせるためです。

== Simutrans内の時間 (参考; ご存知の方は飛ばしてください)
Simutrans内ではシミュレーション時間の最小単位は、実時間のmsec(ミリ秒)で
管理しています。(これをコード上では tick とか ms とか呼んでいます)
ゲームパラメータ bits_per_month (bpm)は、ゲーム時間での1ヶ月が何msecになるかを
log_2 (底2の対数)で表わします。

例:
 bits_per_month = 20 の時
  ゲーム上1ヶ月 = 2^20 = 1048576 msec (実時間) = 約17.5分(実時間)

ちなみにSimutrans オリジナルにおいて、積載率とともに指定できる 1/256 などの
停車時間は、この bits_per_month に対する比率を表わしています。

例:
 bits_per_month = 20 の時の 1/256 停車とはゲーム上の1/256ヶ月を意味し、
  2^20 * 1/256 = 2^12 = 4096 msec (実時間) = 約4秒 (実時間)

(なお、ここでの元になるticksの話はソースコード上の記述の問題であって、
 このticksがどの程度正確なものであるかは未調査です。ご了承ください。)


== タイムテーブルでの時間はTT
このパッチでは、タイムテーブルの時間設定のために
  TT (timetable tick)
という単位を導入しています。
原則としてユーザは時間を全てこの単位で設定します。

1 TT はデフォルトでは 2^8 = 256 ticks です。
(256msec、つまり約1/4秒(実時間))

本来は、計時の最小単位である tick (msec) で指定したほうが極限まで調整が
できるのですが、tickでは値が大きくなり過ぎる場合もあり、
 - 設定時の値の取り扱いが手動では面倒になる
 - 記憶量が増えてしまう (各スケジュールの各行に記録される)
という難点があるため、この単位を導入しています。

なお仕組みの項で説明した last_departure, delay はどちらも
tickで管理しているため、誤差が積もる心配はありません。

また、スケジュール上に記録する時間は現在16bit符号無しで扱っています。
よって各駅間で最大 65535 tt まで指定可能です。
(bpm=20の時で最大ゲーム上16ヶ月、bpm=22なら4ヶ月を表現可能)
ただしタイムテーブル周期やその中でのオフセット時間の指定については、
やはり単位はTTですが、値域は32bit符号無しです。
ただし現在は、各入力フィールドで24bit符号無しの範囲に制限しています。

整理すると、
  計画駅間時間      0〜65535
  周期、オフセット  0〜16777215
が入力できる値の範囲です。

--------------------
= クイックスタート
--------------------
ビルド時に SCHEDULE_TIMETABLE_TTV が指定されている場合
(現状のバイナリ配布では有効にしています)、
路線管理ウィンドウから、時刻表ウィンドウを開いて使うことができます。
これを使うと、簡単に時間計画を作成できるようになります。

  1. 通常通り路線を作成する (この段階では時間設定はしない)
  2. 列車を編成して路線を割り当て、運行させる
     (できればこの時点で最初に必要な編成数を全て運行させておく)
  3. 少なくともスケジュール１周分は走らせる
  4. 路線管理ウィンドウで路線を選択して「時刻表を表示」ボタンを押す。
  5. 列車の列を選択し、上のタブから「計画アシスタント」を選んで手順に従う
  6. 続いて「運行アシスタント」を選んで手順に従う

しばらく運行の様子を見ながら、適宜、時刻表ウィンドウに戻って
修正を加えてください。
各アシスタントの入力方法の詳細などは、後述します。

具合がつかめるまでは、計画アシスタントの設定の中の「時刻表を更新する」
ところまでで止めておいた方が良いかもしれません。
ここまでであれば、駅間を決められた時間で走行するというだけです。
この先「運行周期」を設定してしまうと、列車は始点発時刻の指定に
従うことになるので、この先の設定や調整が複雑になってきます。
ただし、始点発時刻による制御を厳格に行うことで、緩急接続、退避などを
より確実に設定することができるようになってきます。


時刻表ウィンドウが有効でない場合の設定方法は次節以降で説明します。


--------------------
= 使用方法
--------------------
基本的な使い方の流れは以下のようになります。

  1. 路線を作成する (路線作成と編集)
  2. 列車に路線を適用して走行を開始させる
  3. 列車の運行実績時間の記録を見て、路線に計画時間を設定する (路線の編集)
  4. 適宜、列車の遅延をリセットする (列車の詳細ダイアログ、あるいは路線管理ウィンドウ)

ここまでで、個々の列車が、制御された駅間時間によって運行するようになります。
ただしこのままでは、列車と列車のあいだの間隔を制御されたものにはできていません。
↓はオプショナル

  5. 路線に周期時間を設定して列車の間隔調整を行う
     a. 各列車にオフセットを設定する (列車のスケジュール編集ウィンドウ)
     b. 間隔を設定して自動均等設定を行う (路線管理ウィンドウ)

このあとは適宜調整です。

ちなみに簡易タイムテーブル機能は路線化していなくても(列車のスケジュールだけでも)
使用することができます。
ですが、のちのちの増発や調整のためにも路線化されていた方が便利ですし、
自動均等設定を行う場合には、路線化されていることが必須です。

また、各機能には別の組み合わせ方も考えられるかもしれません。

以下では、ゲーム内の各ウィンドウに追加された設定、表示項目、機能を説明します。


----
== 路線・スケジュール編集ウィンドウ
----
停車項目の表示が拡張されています。
スケジュール内の個々の行について (その項目が駅であれば):
{{{
  1) [150] (125) どこか駅 (12,34,0)
}}}
というような表示が行われます。
駅名の前にある二つの括弧内の値はそれぞれ以下のような意味です。

  [xxx]  この駅に設定されている計画時間。単位はTT。
         (前の駅の出発からこの駅の出発までの計画時間)
         Split Time 「計画時間」 入力フィールドで変更できます。(後述)
         計画時間が指定されていない(0)場合は表示されません。

  (yyy)  この駅の出発時に計測された実績時間。単位はTT。
         (前の駅を出発してからこの駅を出発するまでにかかった時間。最新の実績値)
         列車のスケジュール編集ウィンドウで Show RecTime 「実所要時間」ボタンを
         押下した場合のみ表示されます。 (路線には表示されません。)
         実績時間が記録されていない場合は表示されません。

ウィンドウ上部には以下の設定フィールドとボタンが追加されています。

Timetable Cycle 「運行周期」: (数値入力、単位はTT)
  始点発時刻指定運行の場合のタイムテーブル周期を指定します。
  この値が 0 の場合は発時刻指定運行は行いません。
  (この値は一つのスケジュールそのものに指定される値であり、
   スケジュール行の選択には関係ありません。)

"= SumOfSplits" 「総計画時間積算」: (ボタン)
  運行周期 (Timetable Cycle) を自動計算します。
  スケジュール内の全ての駅に指定されている計画時間の総和を
  Timetable Cycle として設定します。
  (スケジュール行の選択には関係ありません。)

Split Time 「計画時間」: (数値入力、単位はTT)
  選択されているスケジュール行に対して、計画時間を設定します。
  これが 0 の時はこの駅での出発時間調整は行われません。
  指定する時間は、前の駅から選択されている駅までの時間 (出発から出発まで) です。

Clear Ttimetable 「計画時間クリア」: (ボタン)
  スケジュール内の全ての行の Split Time (計画時間) を削除 (0にする) します。
  (スケジュール行の選択には関係ありません。)


また、列車のスケジュール編集ウィンドウ (路線ではない) には、さらに
以下のフィールドも追加されます。

Convoy Offset 「始点出発時刻」: (数値入力、単位はTT)
  始点発時刻指定運行を行う時に、この列車の発時刻オフセットを指定します。
  (この値は一つの列車そのものに指定される値であり、
   スケジュール行の選択には関係ありません。)

Show RecTime 「実所要時間」: (トグルボタン)
  各スケジュール行に列車が実際に走行して記録した実績時間が表示されます。

----
== 列車の詳細情報ダイアログ
----
列車の詳細情報ダイアログには、以下のフィールドが追加されています。

Delay 「積算遅延時間」:
  この列車の保持している積算遅延時間が表示されます。
  単位はTTと、msec相当(括弧内)の両方で表示されます。

Reset Delay 「遅延リセット」: (ボタン)
  この列車の積算遅延時間をリセットします。

また以下の各項目は暫定的に表示しています。
将来はどこか別の場所に別の形式で表示するのが望ましいと考えています。

LastDeparture 「最終出発時刻」:
  この列車が前の駅を出発した時のゲーム内時刻の記録です。
  運行開始直後やロード直後は記録されておらず、表示されません。
  単位はTTと、msec相当(括弧内)の両方で表示されます。

GoOn, Now, GoOn-Now  「出発予定 () - 現在() = ...」:
  この列車が現在いる(停車中)、あるいは直前に停車してた(走行中)駅の
  出発予定時刻と現在時刻、およびその差を表示します。
  出発予定と現在は単位 TT で、差は TT と msec相当(括弧内) の両方で表示します。
  走行中は灰色、停車中は青色になります。

  ただし、列車詳細情報ウィンドウの表示更新頻度の関係から、
  表示されない場合があったりもするのでご注意ください。

  駅に停止している時、差の値の意味は
    プラス: 発車予定時刻までまだ余裕がある
    マイナス: 発車予定時刻を過ぎてしまっている
  となります。
  発車予定時刻を過ぎても発車しない場合の要因は、
    * 積載が完了するのを待っている
    * Simutransのシミュレーション時間精度の問題
  などが考えられ、この出発予定からの遅れが極端に大きくなる(目安としては
  100ttを越える、もしくは相対的に見て運行周期の一定割合を越える)ような場合は、
    * 不適当な始点発時刻(オフセット)や運行周期が設定されている
    * プログラム内部のバグ (出発予定時刻の計算を間違っているか、発車判定を間違っているか)
  が考えられます。

Cycle, GoOn, Now  「周期、出発予定、現在」:
  上述の出発予定と現在時刻を運行周期で割った余りです。単位は全てTTです。
  運行周期が設定されている場合のみ表示されます。


----
== 路線管理ウィンドウ
----
路線管理ウィンドウには以下の設定フィールドとボタンが追加されています。
(路線を選択した場合にのみ有効です。)
一部のフィールドは、路線にタイムテーブル周期 (cycle) が設定されている場合のみ
操作可能です。

Reset Delay All 「遅延時間総リセット」: (ボタン)
  路線に所属する全ての編成の積算遅延時間をリセットします。

Pitch 「発車間隔」: (ボタンと数値入力、 単位はTTT)
  自動間隔設定のための間隔(pitch)を入力します。
  ボタンを押した場合は、cycleを現在の編成数で割った値が自動計算されます。

Auto Offset 「設定開始/修正値」: (ボタンと数値入力、単位はTTT)
  右の数値入力には、間隔の基底値(base)を入力します。
  ボタンを押すことで自動オフセット設定を開始します。
  自動オフセット設定が行われている間はボタンは押下されたままの状態になります。
  全ての列車へのオフセットの設定が完了すると、ボタンは元に戻ります。


--------------------
= 列車の時間情報表示 (ツールチップ、情報ウィンドウ)
--------------------
タイムテーブル機能に関係する時間を設定している列車については、
その情報ウィンドウや列車のツールチップで以下のような情報が表示されます。
(その列車の遅れや先行の量によって表示する色は変化します。)

なお予定出発時刻を過ぎてもすぐに列車が発車しないのは、他でも延べる通り
Simutransのシミュレーションの仕組みに起因する仕様です。
  「発車間際の駆け込み乗車は大変危険ですのでおやめください」
と心の中で車内アナウンスを入れてください。

----------
== ツールチップ
(列車にマウスオーバ、あるいは「表示設定」の中で「常に車両の状態を表示」を選択)
(ビルド時に SCHEDULE_TIMETABLE_CONVOITIP の指定が必要です。)
列車の状態に応じて以下のようなツールチップが表示されます。
時間は全て単位 TT です。

=== 駅で停車中のツールチップ
「常に車両の状態を表示」あるいは「マウスオーバで車両の状態を表示」に
設定されている時に表示されます。

"Ntt for Departure"  「Nttで出発」
  駅を出発する予定時刻までの残り時間を示します。

"Suspended Ntt"  「延発 Ntt」
  駅の予定出発時刻からの経過時間を示します。

上の二つは、時間差の範囲によって
   緑(計画内とみなせる)、黄色(計画を外れてきている)、オレンジ(異常があると考えられる)
の3段階で色が変わります。

"Loading (A->B%) for Ntt" 「積載(A->B%) 待ちNtt」
  積載待ち時間を指定している場合に、出発までの積載量と残り時間を示します。
  この表示は、列車にタイムテーブルが設定されているかに関係ありません。
  オリジナルの "Loading (A->B%)"「積載(A->B%)」 を拡張したものです。

"Loading (A->B%)"「積載(A->B%)」
  列車に待ち時間設定もタイムテーブル設定もされていない場合、
  最低積載量が指定されていればオリジナルのこのツールチップが表示されます。

=== 駅間を走行中のツールチップ
表示の設定にかかわらず条件があてはまれば「問題あり」として常に表示します。
なお線路や道路の空きを待っている時には表示されません。
(要仕様検討)

"Delayed Ntt!" 「遅延 Ntt!」
  列車の積算遅延時間が大きすぎる場合にその遅延量が表示されます。
  現在は暫定的に、遅延が 100tt を越えている場合に表示します。

----------
== 列車情報ウィンドウ
(列車をクリック、または時刻表ウィンドウで列車カラムをCtrl+クリックでも)
(ビルド時に SCHEDULE_TIMETABLE_TIMINGBAR の指定が必要です。)
列車情報ウィンドウには運行時間情報表示バーが表示されます。

このバーは中央を定刻として、
  現在 - 次発予定がマイナス (先行): 左へバーが伸びる
  現在 - 次発予定がプラス   (遅延): 右へバーが伸びる
という動きをします。中央の数値表示部分だけは固定の長さを持っており
この幅が変化することはありません。時間差が一定量を越えた場合には、
この中央部分から左あるいは右へバーが伸びます。

数値は左から
  現在時刻     差    発予定時刻
となります。
表示される値は運行周期の倍数を引いてあります。
(数値の意味は、次節の「詳細情報ウィンドウ」の中にある N, D, M と同じです)

定刻で運行している場合、中央部分の色は
  走行中: 暗い緑色 (DARK_GREEN)
  停車中: 緑色 (GREEN)
と変化します。

走行中は予想される遅延量が甚大な場合に色が黄土、橙、赤と変化していきます。
停車中はこれに加えて、先行が大きすぎる場合にも色が変化します。

なおバー領域をクリックすると、新たな時刻表ウィンドウが開き、
この列車と同じ路線に所属している列車達の時刻表を見ることができます。
(試しのおまけ機能なので、将来変更される可能性が高いです。)

----------
== 詳細情報ウィンドウ
(列車情報ウィンドウで「詳細」ボタンをクリック)
列車がタイムテーブルによる運行(計画駅間時間、運行周期指定のいずれか
または両方が指定されている)されている場合、以下のような情報が追加されます。
時間は全て単位 TT です。

"LastDepart: Ltt   Delay: Jtt" 「前駅出発：Ltt  積算遅延：Jtt」
  前駅を出発した時刻 L と、現在の積算遅延量 J が表示されます。
  前駅出発時刻は、ゲーム開始を0としたゲーム内絶対時刻です。

"+Btt: Now: N  NextDepart: M  = Dtt WHENCE" 「+Btt: 現在：N  発予定：M  = Dtt WHENCE」
  現在の時刻 N と次の駅 (停車中は停車中の駅) の出発予定時刻 M、
  およびその差の絶対値 D が表示されます。
  NとMは、ゲーム内絶対時刻 B からの経過時間で示します。
  この値はタイムテーブルの運行周期 (設定されていない場合は、計画駅間時間の総和)
  の整数倍が選ばれます。(NとMの表示が負にならないように選択されます。)

  WHENCE の部分には、差の符号によって以下のいずれかが表示されます。

    "Future" 「先行」:  N - M < 0
       予定時刻より前です。停車中なら、定刻待ちになります。
       走行中なら、次の駅を定時発できる可能性がまだあることを示します。

    "OnTime" 「定刻」:  N - M = 0
       予定時刻に丁度なりました。停車中なら、間も無く発車します。
       走行中なら、次の駅での定時発には間に合いません。

    "Past"   「遅れ」:  N - M > 0
       予定時刻を過ぎました。停車中なら、間も無く発車します。
       走行中なら、次の駅での定時発には間に合いません。

  注意:
    運行周期時間を指定しての始点発を行っている場合、このことは M に
    反映されません。列車がスケジュールの最終区間 (スケジュールの
    最初の駅に到着する前) を走行中 は、期待とは異なる状態報告がされるでしょう。
    スケジュールの中の計画駅間時間の総和が、運行周期時間と等しくなるように
    設定されていれば、この違いは発生しなくなります。

時間差が計画内とみなせる場合、停車中は 青(DARK_BLUE)、走行中は 緑(DARK_GREEN)
停車・走行中にかかわらず差が中程度なら 茶色(BROWN)、
より大きい場合は 赤(RED) で表示されます。
(値の範囲のは次節を参照してください)

----------
== 時間差の範囲による分類
現在の実装では、時間差(現在 - 予定)を以下の固定値の範囲で分類しています。
この分類結果によって色を変えている表示があります。

(表の下の項の範囲はより上の項の範囲を除きます)
   -200から  +20の間:   最適運行
   -500から  +50の間:   計画内のずれ
  -1000から +100の間:   計画を外れたずれ
        より大きな差:   深刻な乱れ
(先行(負)に比べて遅れ(正)の側は10倍敏感なことに注意してください)

簡単に図示すると以下のようになります。(スケールはめちゃくちゃです)
{{{
←先行                            現在                          遅れ→
          -1000       -500   -200  0  +20  +50   +100
 .....-------+----------+------+---+---+----+------+------...........
 極端な先行     計画外   計画内   最適   微延  遅れ   問題になる遅れ
}}}

固定値での範囲づけですのであくまで目安として考えてください。
運行計画によっては絶対値の大きな負の値(大きく先行)になることも充分に考えられます。
ただし別述する「強制段落ち」という現象が発生すると、「極端な先行」として示される場合があります。

なお時間差が負(先行)の時の分類は、駅に停車している時にのみ行います。
走行中は(時間差の中に次の駅までの走行時間も含まれているため) 正(遅れ)の時にのみ
分類しています。

将来的には、路線の事情や計画に合わせた範囲づけを行うことも検討しています。


--------------------
= 時刻表ウィンドウ
--------------------
開発途上の機能ですが、路線に所属する全ての列車の運行計画を、
時刻表のようなスタイルで表示できます。
これを使うと各列車の各駅での出発時刻を比較して見ながら計画時間を
調整することができます。
また「アシスタント」と呼ばれるパネルを使うことで、路線の時間計画作成と
路線に所属する列車間の運行間隔調整を簡単に行うことができます。

----
== 時刻表ウィンドウを使用上の注意
----
時刻表ウィンドウを開いているあいだに、路線に列車を追加、削除したり、
または路線自体の削除や列車自体の売却をしたりした場合、
現在の時刻表ウィンドウは異常動作を起こす可能性があります。
(少なくとも、今見ている時刻表ウィンドウにはこの変更は反映されません。)

これらの路線、列車の操作を行う場合には必ず一度、時刻表ウィンドウを
閉じてから行うようにしてください。

列車個別のスケジュールを編集したことで、路線から列車が外れる場合もこれに含まれます。

----
== 時刻表ウィンドウの出し方
----
路線管理ウィンドウの中で路線を選択して、
"View Timetable" 「時刻表を表示」ボタンを押せばこのウィンドウが開きます。
この時、
  どれか路線を選んでいる:
    その路線に所属する全ての列車を表示
  路線フィルタで一部の路線だけを選んでいる (しかし特定の路線は選んでいない):
    フィルタで選ばれた全ての路線の全ての列車を表示
という動作をします。

例えば同一線区を走行する複数の種別をまとめて表示するには
路線名に共通の文字列を入れておいてフィルタでより分けた上で、
"View Timetable" (時刻表を表示) を押します。

例:
それぞれの路線の名前を
  東海道本線 東京口 普通 東京-静岡
  東海道本線 東京口 特急 「踊り子」
としておいて、フィルタで「東海道本線 東京口」と入力すれば
この二つの路線にしぼられます。この状態で(路線をクリックせずに)
"View Timetable" ボタンを押すと、一つのウィンドウに
この両方の路線の全列車が表示されます。

注意:
  現状では、列車の割当てられていない路線を選択して開いても、
  時刻表には何も表示されません。

----
== ウィンドウの表示
----
ウィンドウの上部には、路線を選択するセレクションボックスに続いて
時刻表表示、およびそれへの操作ボタンなどが並びます。
ウィンドウ下部のチェックボックスを選択することで、
時刻表の中に表示される情報が増えます。
(この中の「周期時間表示」とは、各駅での発車時刻を運行周期で
割った余りにするかどうかを選択します。)

また、右下にある二つのボタンはそれぞれウィンドウの下部と右部に
追加パネルを表示させます。

下部: 乗物一覧 (編成リスト)
  現在、時刻表に表示されている編成が一覧されます。
  これといった設定などはできませんが、右側に表示されるバーで
  各列車の先行・遅延の様子を見ることができます。
  (情報は、列車の情報ウィンドウに表示されるものと同じです)

右部: アシスタント
  列車のダイヤ設定の作成支援を行う機能です。
  「計画アシスタント」と「運行アシスタント」の二つのパネルを
  上部のタブで選択できます。
  詳細は後述します。


時刻表シートに最初に表示される値は、列車が当該駅を出発する「時刻」
(に相当する値)です。"v" と表示されている場合は、その駅を通過することを
意味します。(通過は自動認識ですので、路線の組み合わせによっては
誤って表示される場合もあります)

----
== 列車と時刻表の対応
----
列車一覧の左端にある仮ラベルと、時刻表の上端に並ぶ列見出しとが対応します。

仮ラベルは、列車名が以下の形式を持っている場合に自動抽出されます。

   路線名: ラベル部

列車の所属する路線名に続いて一文字の半角コロン(':')そして空白があると、
これより後をラベルとして使用します。
例えば
  東海道線 普通
という路線名の時に
  東海道線 普通: 1302M
と列車名がつけられていれば、時刻表には
  1302M
と表示されます。


----
== 表示の更新
----
時刻表ウィンドウの内容はウィンドウを開いた時点での各列車の持つ時刻情報であり、
自動的には更新されません。

"Refresh Table"「時刻表の更新」ボタンを押すことで、
最新の各列車の設定値や実績値を採取され、表示が更新されます。

----
== セルの選択
----
表示中のあるセルをクリックすることで、そのセルを選択できます。
また、左端に並ぶ駅名をクリックすると、その行全体(駅での各列車の全ての停車)を、
また、上端に並ぶ列車名をクリックすると、その列全体(列車のスケジュール全体)を、
それぞれ選択することができます。
また表の上左端(何も書かれていないところ)をクリックすると、全ての選択が解除できます。

値を変更できるセルを選択すると、ウィンドウの中央部に数値入力フィールドが
表示され、値を変更できるようになります。(時刻の修正については後述します。)

駅の選択は時刻での並び替えに、また列車の選択はスケジュールの更新などで利用します。

----
== 行や列のラベルの修飾キーつきクリック
----
時刻表シートの行や列のラベルを、Control や Shiftキーを押しながらクリックすると、
シートの表示についてのいくつかの操作が可能です。

Control+列のラベル (列車の列)
  列車の情報ウィンドウを開きます

Control+行のラベル (駅の行)
  駅の情報ウィンドウを開きます

Control+左上隅
  表の内容を最新のものにします (「表示を更新」ボタンと同じ機能)

Shift+列のラベル
  列を隠します
  列車の計画時間の列をクリックした場合はその列車の表示を隠します
  それ以外の列をクリックした場合は対応する表示オプションをオフにします

Shift+行のラベル
  行を隠します
  駅の停車時刻の行をクリックした場合はその駅の表示を隠します
  それ以外の行をクリックした場合は対応する表示オプションをオフにします

Shift+左上隅
  隠されている全ての列車と駅を再表示します。

Control+Shift+左上隅
  表示オプションを全て有効にし、さらに隠されている全ての列車と駅を再表示します。
  

----
== 並び替え
----
表内の各列車をいくつかの方法で並び替えることができます。
"Sort"(並び替え)ボタンの右にあるコンボボックスの中で、並び替え方法を選択します。
  計画時刻  選択している駅で計画されている出発時刻でソート
  実績時刻  選択している駅を実際に出発した時刻でソート
            (列車の走行実績時刻の記録が足りていない場合は無意味です)
  ラベル    列車につけられた(現在は)仮ラベルでのソート
  名前      列車名でソート
  ID        列車が内部で持つID数値でソート
            (デフォルトの列車名の先頭につく()内の値です)
時刻によるソートの場合、行が選択されていない場合は時刻表の最初の駅での時刻によるソートになります。

----
== 時刻表の修正
----
表の中で各列車の以下の値は、数値入力によって修正することが可能です。

  計画出発時刻
    駅の出発時刻だけを変更します。

  計画駅間時間
    変更した区間より後の駅の出発時刻を全て修正します。
    また運行周期も合わせて変更されます。

  運行周期
    運行周期を変更するとともに、時刻表の最後の区間の計画時間を変更します。

変更するには数値を入力した上で、入力フィールドの右にあるボタンを押します。
列車の時刻を変更すると、これに合わせて同じ路線に所属する全ての列車の値も
変更されます。
変更した値は茶色で表示されています。

ただし、これによって個々のセルの値を変更しただけでは、実際の列車の
スケジュールには適用されません。
編集を終えた時刻表を各列車のスケジュールに反映させるには、
"Publish Revised" 「時刻表の改定」ボタンを押します。

----
== 計画アシスタント
----
時間計画が適用されずに走行している路線、編成に対して、時間計画作成の
支援をするパネルです。
すでに計画運行されている時刻表の修正時の助けにも使用できます。

手順は中で示されている通りです。
# 将来的に、ドキュメントを整備します。
ゼロから時間計画を作る時は、編成(列車)を時刻表の列で選んでから
ステップ1から順に進めてください。
「または」で並んでいるところは、どちらかを行えば大丈夫です。

注意点:
  時刻などの値を数値入力フィールドで入力して修正する場合、ミスを防止するために
  原則、その右にあるボタンを押してはじめて設定されるようにしてあります。
  値を入力してから、その右のボタンをクリック、これを繰り返してください。
  (将来的には操作性を改善しようと考えています)

注意点: 
  見積り時間を距離/速度で算出する場合、元にする距離は正確なものとは限りません。
  またコーナリングや駅の進入、出発での減速、積載量による速度の変化なども
  一切考慮されていません。あくまで超理想的な走行をした場合の目安として求め、
  必ず実際の走行時間を見ながら補正してください。

ステップ3まで進んだところで、時刻表を改定すれば
(始点発車時刻指定の無い) 駅間時間安定なだけの設定が作れます。
他の列車との時間関係まで決めていきたければ、ステップ4で運行周期も設定して
次は運行アシスタントに進んでください。

# 実はステップ4は、運行アシスタント側に入るべきだったかも。

----
== 運行アシスタント
----
「計画アシスタント」で列車単体の安定運行が実現したら、次は
一つの路線に所属する複数の列車間の関係を決めていきます。
これを行うのが「運行アシスタント」です。
このアシスタントも示されている手順の通りにたどれば大丈夫です。

ステップ1: 時間間隔を直接数値で指定する(値を入力して「設定する」ボタンを押す)か
  走行させたい列車の本数を入力して、計算させてください。

ステップ2: 運行周期の中での最初の列車が始点を出発する時刻を決めます。
  すでに時刻表に始点発車時刻を入れている場合は、これらの中から最も早い
  ものを選んで採用することもできます。

ステップ3: まずは現在走行中の列車にその場で計算して割当てます。
  内部では、「現在いる位置が最も(一周した後の)始点に近い」順番に
  始点出発時刻をわりふっていきます。
  ただしこの時、最も始点に近い列車に割当てる時刻は、この列車が
  始点に到着するであろう時刻を予想して割当てています。
  つまり、かならず Shift(「ずれ量」) になるわけではありません。

  始点のところに表示された値が (場合によってはソートしなおしてください)
  問題ないようだったら「時刻表を適用」を押して運行に反映させます。

注意:
  現在、列車の順序判定は完璧ではありません。
  この次のステップにあるオフセットの自動再設定を利用した方が、
  より正確に走行順序に沿った時刻設定がされます。適宜、併用してください。

ステップ4: 実際に走行している中で各列車が始点に到着したときに
  それぞれに最適な始点出発時刻を自動的に再設定します。
  「1周期分だけ実行」を押すと、各列車にひととおり自動再設定が終ったところで
  自動設定は行われなくなります。この後に時刻表を見れば、実際に自動設定された
  時刻を見ることができます。
  一方で、「常に調整し続ける」をチェックすると、チェックされている間は
  ずっと、自動再設定を続けます。したがって、タイミングによって時刻表の上に
  表われる値が変化する可能性があります。

ステップ5: 列車名の自動設定便利ツールです。
  【路線名】: 【接頭】【番号】【接尾】
  という形の名前を路線の中の全ての列車に割当てることができます。
  先頭に路線名を入れるかはチェックボックスで切り替えられます。
  接頭や接尾は空でもかまいません。
  番号部分は、番号づけを開始する値を入れますが、この時、先頭に0を並べておくと
  並べただけの桁数で番号を作成します。
  例えば、
    【さくら】【1】【号】
  としておけば
     さくら1号  さくら2号  ... さくら10号 ... さくら100号 ...
  となっていきますが、
    【普通】【0005】【M】
  としてみると、
      普通0005M  普通0006M  ... 普通0010M ... 普通0100M ...
  となっていきます。
  各欄に文字列を入れてEnterを押すと、サンプルの部分に最初の編成に付けられる
  名前が出ますので、いろいろ試してみてください。

注意:
  現在のアルゴリズムでは、ある駅間に複数の編成が存在する場合、
  その間で番号が前後してしまうことがあります。
  なお運行と名前の間に直接の関係は無いので、走行には支障はありません。


----
== その他コメント
----
各列車(路線)について、先頭と末尾にはスケジュール上の同じ駅が表示されます。
例えば
  A - B - C - B
というようなスケジュールを設定していた場合、表の上端と下端の両方に A が
表示されます。
(このようにしないと、駅間時間をスマートに表示する方法が無かったため、こうしています)

複数の路線、特に異なる区間を走行するような路線を同時に表示させた場合、
期待とは異なる表示(駅の並び方)となる可能性があります。
複数の路線の自動マージは結構面倒なアルゴリズムです。
普通列車のスケジュールにあった駅を、優等列車が「通過する」のか
それとも「線区が違う」のか、この判断は厳密にはできません。

現在、各駅間の距離は一応、乗物の通れるルートを計算させて求めていますが、
複数の路線が重なって表示されている場合 (例えば、普通と優等が並んで
表示されている場合、あるいは鉄道とバスが並行路線化している場合など) は、
この距離計算が正しく動作しない可能性があります。
これに備えて、内部では「乗物のルートで計算した距離」と「マンハッタン距離」
(x,yそれぞれの差の絶対値の合計) とを比べて、より大きい方を表示しています。
(計画アシスタントで駅間時間の自動計算に使う距離もこの値です。)

これらの駅間距離を使って、優等列車が「通過する」のか「線区が違う」のかの
判断を行っていますが、厳密に普通が通るルートと同じとは限らない
(例えば駅に通過線があるなど) ため、三角不等式に入れつつマージンを加えています。
このマージンとしては、駅の施設全体の広さ(x幅+y幅)を使用していますが、
少々広すぎるかもしれません。特に付属建築物によって立派な駅舎がついている
駅では、この判定の間違いが起こりやすくなるでしょう。

しかし逆にこのルーズなマージンによる判定のおかげで、競合二社間の
ダイヤを比較をしたり、同じ駅のあいだを走る列車とバスの比較をしたりなども
可能にはなっています。

列車によっては通過する駅を選択しての、出発時刻ソートは完璧ではありません。
(その駅に関する通過列車の時刻情報がありませんので仕方ない)
一応、上述した距離の関係を利用して線形補間した値を使っていますが、
いつの間にか普通が優等を抜き返していたりすることもあるかもしれません。
(これの別の原因としては、今のTTTが「出発時刻」しか管理していないということもあります。)


----
== 現状の問題と課題 (TTT-038)
----
  * 優等の表示に普通をマージする処理が完全ではない
  * 途中折り返しのマージのしかたによっては表示がおかしくなりそう
  * 全く異なるところを走行する複数の路線を表示させると大変なことになりそう
  * 各アシスタントでの順序や時間の推定において、
    駅間が長い and/or 駅間に複数の編成がいるといった場合に
    計算結果が利用に適さない(順序が間違っている、時間の精度が悪すぎる)ことがある
    (経路計算の利用を増やすことによってある程度は解決できるが、処理が重くなる)

TODO:
  * 時刻表情報の CSV 形式などでのファイル入出力
    やはり餅は餅屋ということで、Windows用のダイヤ編集ソフトなどに
    任せた方がいいのかもと考えています。
    今は一応、Simutrans単体でも完結して使えるレベルまでは整備しようと考えています。
  * デザインのブラッシュアップ
  * 使い方の説明


--------------------
= その他、実験的機能
--------------------
このほかに、TTTによる運行がスムーズになることを目指して実験的に入れている
機能があります。
主に「期待しない段落ち」対策の実験です。
# 以下、演算子はほとんどの場所で、C言語のものを使用します。
# '*' は乗算、'/' は除算、'%' は剰余を求める演算です。
# 比較は '>=' は大なりイコール、'<=' は小なりイコール。

# 式に誤りを見つけられましたら、是非ご指摘ください。

== 期待しない段落ちの発生
(運行周期とオフセット(始点出発時刻)を指定している列車にのみ関係する話です。)
基本アルゴリズムでは、始点に到着した時点で次の出発時刻は
  go_on_time = N * Cycle + Offset  (ただしここで N は非負の整数)
を満たすNのうち、go_on_time >= now となる最小の N を選んでいます。

もし列車が計画で決められた運行時間を*ぎりぎり*で満たせずに始点に到着した場合、
本来期待していたNより1つ大きいNを選んでしまうことになり、最悪の場合、
1 Cycle 分だけ出発が待たされることになります。
(いわば強制的に段落ちさせられた状態です。)

計画時間に対しての余裕時間の挿入が適切であり、全編成が安定した運用に入っていれば
まずこれは発生しないのですが、計画途中や試験運用中はそこまで至る前に
運行の乱れが頻発し、計画通りの施設利用や退避などがなかなか実現できません。

なお上の計算はプログラム上は以下のようなコードになっています。
(全て整数での演算、切り捨てありなことに注意してください)
  go_on_time = (now - offset + (cycle - 1)) / cycle * cycle + offset;
乗算より前の部分が上で言う「適切なNを求めること」に相当します。
整数除算の切り捨てを利用しています。
現在時刻に(cycle-1)を加えて割ることで、次のcycle周期の頭の時間を出します。


== 対策実験1: 始点出発時刻への許容遅れ量の挿入 (TTT-037から)
一定範囲内までの遅れであれば吸収できるように、マージンを挿入してみました。
現状は、運行周期 (Cycle) の 10% までは遅延しても良いようにしています。
(マクロ LATE_MARGIN_BY_CYCLE() 内で固定。設定要素にするべきかどうかは要検討)
予定出発時刻より遅れている場合は、この遅れも積算してただちに出発します。
通常の駅間時間設定による運行と同様、この先で遅れを取り返せれば取り返します。

プログラム上の計算式は以下のように変化しています。
  go_on_time = (now - offset + (cycle *9/10)) / cycle * cycle + offset;
元の式の (cycle-1) を加える部分を (cycle *9/10) にすることで、
cycleの10%分だけは、前のcycle周期に喰い込む可能性が出ます。
  

== 対策実験2: 始点出発時刻を常時修正し続ける (TTT-037から)
路線に Persisten Auto-Offsetting (永続的な自動オフセット) を指定できるように
しました。
ただし現在は、時刻表ウィンドウの「運行アシスタント」の中からしか指定できません。

これまでの Auto-Offset は以下のようなアルゴリズムでした。

(1)Auto-Offsetが開始されてから最初に始点に着いた列車:
    go_on_time = N * Cycle + M * Pitch + Shift  (ただしここでN、Mは非負の整数)
  を満たすNのうち、go_on_time >= now となる最小のNとMを選んでいます。
  (最初に示した式の中の Offset が (M * Pitch + Shift) になるわけです。)
  この (M*Pitch + Shift) をこの列車の Offset に設定します。
  またこの値を直近のOffsetとして覚えておきます。

(2)以降に始点に着いた列車:
  覚えておいた直近のOffsetにPitchを加えて、この列車の Offset に設定します。
  直近のOffsetの記憶は、この値に更新されます。

これを路線に所属する全列車に対して適用するまで続け、適用しきったら
Auto-Offsetを終了します。

この方法は、運行中の列車を必ず Pitch 間隔にするように動きますが
(少なくとも、Offsetに残される値はそうなる)、問題があります。
「現在運行している列車同士の間隔の中に Pitch より大きいところがあった時」
このような時、この方法では段落ちを発生させてしまい、列車が詰まってしまいます。

これに対して、Persisitent (永続的) では、全ての列車に対して常に上の(1)を
行います。また、一度全列車に対する処理が終った後も、解除されるまでAuto-Offsetを
続けます。
これによって、各列車は自身が到着した時間の後に来る直近の
  M * Pitch + Shift
の時刻に出発するようになります。しかし、各パラメータの具合と
列車の走行状況によっては、ところどころ Pitch の倍数分だけ間隔が開いてしまったり、
複数の列車に同じ Offset が割当てられる場合もありえます。

新計画のダイヤが安定するまではこのPersistenで走らせておいて、
全種別の運行が安定してきたように見えたら、Persistenを外し、
明示的なOffset調整をしてダイヤを仕上げる、というような使い方が考えられます。

もちろん、路線によってはずっと Persistent のまま走らせておくという手もあるでしょう。
ただし少し実験してみた限りでは、このPersistentのままにしておくと、元の計画に無理があった場合にその無理に気付きにくくなります。
たまに時刻表を見て、歯脱けが無いか、あるいは複数の編成に同じ時間が設定されていないか、確認しておいた方がいいでしょう。


== その他検討中: 始点での積算遅延時間の取り扱い
周期時間運行(+オフセット)の場合、現在の実装では、それまで溜ってきた遅延時間が原則、始点でリセットされてしまいます。

元々の始点発時指定運行を追加した時には
  周期とオフセットを指定して運行しているのだから、
  始点では厳密な時刻に従えばよく
  駅間時間で溜った遅延は無視するべきだ
という具合に考えていました。
このようにすれば、もしダイヤが滅茶苦茶に乱れて遅延時間が過剰に溜っていても
始点を出る時には運行周期の範囲内に回復したことになる、という自動段落としの役目を持っていました。

ですが、状況によっては必ずしもこれは適当ではなく、
遅延時間を積極的に利用した方がいい場合もあるかもしれません。
(遅延が過剰に溜っている分は、周期で割って余りにすればよい)


--------------------
= Simutransオリジナル機能との関係
--------------------
スケジュール編集ウィンドウでは、Simutransオリジナルの
積載率指定や積載待ち時間などの入力もそのまま残っています。
スケジュールに計画所要時間や運行周期を入力しなければ、
オリジナルどおりの動作になり、積載率指定や積載待ち時間指定が有効になります。

両方を指定している場合は:
  遅延している (停車目標時間が負): 旧来からの積載率指定などが有効
  定時内運行中 (停車目標時間が正): 計画時間による調整が有効
となります。


--------------------
= ご利用上の注意点とお願い
--------------------
このパッチは現在、αクオリティです。
作者自身、この機能を充分に使い込み、試しているわけではありません。
突然、あなたのマップのあちこちの駅で列車が詰まりまくってしまっても
損害賠償や振替輸送に応じることは出来ませんのでご了承ください :-)

バグのご報告や機能改善のご提案はウェルカムです。
(ただし充分に対応できる余裕はございませんので対応が遅れましてもご了承ください。)
ご連絡は日本語フォーラム
  Japanese Simutrans Forum
の該当トピックへお願いいたします。
(どうしても個人的にという場合は、wackdone@gmail.com へメールください)

また以下のような形でお手伝いいただけると助かります。
  * 動作評価、特に複雑な路線を組んだ場合など
  * Windowsなどのプラットフォーム用の実行バイナリ作成、配布と動作確認
  * 使用方法、チュートリアルや応用の説明ページ化や動画化
  * ドキュメントやコード内コメントなどの英語化 (私の英語は偽物英語orz)
  * コードの拡張
これらを経て、ある程度の動作の確認と支持が得られれば、
将来的には本家へ取り込んでもらえるようにしたいと考えています。

なお、みなさんに是非この機能を使ってより深くSimutransを楽しんでいただけたらと
願っております。
この機能を使ったマップ紹介ページや動画などを公開して頂くのは大歓迎です。


--------------------
= 既知の問題点と課題
--------------------
課題: 始点発時刻指定でのダイヤ乱れ
  ← 実験ロジックを入れて有効性の検証中。
  運行の遅れがたまり過ぎていて、列車の始点への到着が予定されていた始点発時刻を
  過ぎてしまうと、出発が最悪 cycle 分だけ遅れてしまうおそれがあります。
  (当然、続行列車も詰まります。)
  これを自動的に解消する (スジを自動で落とすなど) ロジックとして
  いまいちいいものが見つかりません。
  現実世界でも完全な機械化はされていない (Computer Aided はある) ので、
  そうそう上手くはいかないでしょう。
  今の機能では、(等間隔運転の場合に限って) offsetの自動再設定機能を使えば
  ある程度の回復はできます。
  しかし、現状から計画までのあいだをスムーズにつなぐものではありません。

課題: 時間調整の精度
  Simutransのシミュレーションの仕組みからくる制限ではあるのですが、
  現在 slack==1000msec (==1sec) であっても、なかなか正確な発時が守れません。
  この機能が有効な場合には、convoi の wait_lock にも少し手を入れなければ
  ならないかもしれない。(ただし確実に重くなっていきそうだが)

課題: GUIのセンスが悪い
  この機能を使用しない場合にはうるさくてしょうがないだろうし、
  列車や路線によっても表示させたいものは変わるだろう。
  スケジュール編集画面はタブ化するなり、「表示の設定」でいじれるなりしないと
  いけないかもしれない。

課題: TTの大きさの調整
  現状、1TT と 1tick の比率はハードコードされています。
  (ソース内では dataobj/fahrplan.h の中の TTT_SHIFT で指定されています。)
  bits_per_month のようにゲーム設定で変更できるようにするかは検討中です。

課題: 時間や時刻の表示
  現状、ほぼ全ての状況で出現する数値はこの TT 単位のただの整数値です。
  ゲーム時間に対応させて "h時間m分" であるとか "h時m分" であるように
  表示、入力させることはまだ考えられていません。
  (ゲーム中で左下に表示される年月日時分は、日より下の単位が一定量ではありません。
   これはSimutransが「ゲーム内1ヶ月の長さ」をbits_per_monthで扱うためです。)
  TTTで扱う時間は、それ独自で何らか読み易い、またイメージしやすい
  フォーマットを定義した方が良いと考えられます。

問題と課題: 中継点の扱い (間隔時間を設定できるようにするか？)
  今は中継点にも値が入力できてしまうが、これを設定すると動作不具合が起きうる。
  とりあえず考えられる案としては
  * 中継点に設定した所要時間も使用する。
  * 停車はしないので遅延時間を再計算するのみ。
  (中継点を通過する時点で余裕が出ていれば、遅延がマイナスに振れて
   次の駅での停車がのびる。遅れていれば逆)
  駅だったところを破壊して中継点になってしまったり、その逆だったりした時に、
  こうしておけばタイムテーブルの引き継ぎがうまくいくと考えられる。

課題: 発-発間時間を発-着と着-発に分割するか？
  今の駅発→駅発の時間を  駅発→駅到着 と 駅停車時間 に分けるかどうか。
  (分けたところで、アルゴリズム上はまとめて扱う)
  ダイヤ設定的にはこの方が使いやすくなるだろうが、記憶量 (セーブデータ量も)
  に大きく影響してしまう。

  中継点の時間を扱えるようにすれば、駅到着直前に中継点を入れることで
  擬似的に「発-着」「停車時間」に近い分離ができる。
  (チューズシグナルを使っている場合などはやりにくいかも)

課題: 実績時間の表示
  ← とりあえず、「時刻表ウィンドウ」で対応してみたが、
     「時刻表ウィンドウ」の動作が重いという別の問題がある。
  現在、
    実績時間の表示は列車スケジュール編集で
    タイムテーブルの調整は路線スケジュール編集で
  に分離してしまっており、タイムテーブルの調整がやりにくい。
  どちらも路線スケジュール編集で見られるといいのだが。
  ただし、路線編集側では「どの列車の実績時間を見るのか」という選択が
  必要になってしまう。

夢: ダイアグラム編集
  グラフィカルに編集できるとかっこいいなぁ。。。
  せめて現在のスケジュールを外部とのあいだでCSVなどでimport/exportできるように
  すれば、外部ツールに頼れるだろうか。

課題: いろいろと
  問題・課題はたくさんあれど、
  * バイナリ配布
  * ドキュメント、使用ガイドのわかりやすいものを作る
  * (セーブバージョン番号をまともにするには特に) 本家へ働きかける
  などが普及のための最優先課題だろうか
