// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Prof. SONE's Laboratory, the Univ. of Tokyo.)
// stnobj.hh --- class station_obj and related classes and structs
// $Id: stnobj.hh,v 2.4 1994/12/27 11:49:38 rt Exp $

#include "globvar.hh"
#include "readdata.hh"
#include "RefTable.hh"
#include "enumerat.hh"
#include "matrix.hh"

#ifndef ___STNOBJ_HH
#define ___STNOBJ_HH		// こうしておくと2度インクルードしても大丈夫！

class train;	// こうしておかないとまずい

// 駅に向かっている列車を示すデータ
struct to_station {
    const train* tr_ptr;	// 列車オブジェクトへのポインタ
    int ilno;	// 駅にアプローチする線路の番号
    int voie;	// 入るべき番線
    int notrw;	// 駅で待つ（先行させる）べき列車の本数
    int olno;	// 駅を出る線路の番号
    bool is_pass;	// この駅は通過
    double taudx;	// この列車が前駅出発時に持っている遅れ
    double tarrive;	// 到着すべき時刻, 駅制約考慮済みでないもの
    double tarr_delay;	// 到着すべき時刻の駅制約考慮済みのものと
			// そうでないものとの差
    double tstop;	// 駅停車予定時分

    to_station() {
        tr_ptr = 0;
        tstop = tarr_delay = tarrive = -3600;
        ilno = olno = voie = 0;
        is_pass = false;
    }
};

// 駅在線データ構造体
struct from_station {
    const train* tr_ptr;	// 列車オブジェクトへのポインタ
    int voie;	// この列車が発車する番線
    int notrw;	// 駅で待つ（先行させる）べき列車の本数
    int olno;	// この列車が駅を出る線路の番号
    double tarrive;	// この列車が到着した時刻
    bool is_pass;	// 「通過列車です」フラグ
    bool is_at_station;	// 「現在駅にいます」フラグ
    bool do_not_depart;	// 「出発してはいけない」フラグ
    double tdept;	// 発車すべき時刻, 予想
    double tdept_delay;	// 発車した時刻, 実績値と予想との差
    double taudx;	// この列車が前駅出発時に持っている遅れ

    from_station() {
        tr_ptr = 0;
        tdept = tdept_delay = tarrive = -3600;
        voie = 0;
        is_pass = is_at_station = false;
        do_not_depart = true;
    }
};

// 駅到着・出発間隔保証を主目的とする駅オブジェクトクラス
class station_obj
: public NoRefTable<to_station>, public readdata {

  private:
    // テストをする場合は public 指定するとよい

    bool first_headcal_ended;	// 最初の headway_cal が終わったら true

    int stnno;			// この駅の駅番号
    int niolno;			// 駅にアプローチする線路の数
    int nvoie;				// その駅にある線路数
    station_obj_type stnobjtype;	// タイプ
    double out_of_station;	// 駅間停車時の停止位置
//     const station_obj* nextstnobj;	// 隣の station_obj

    // 最小時間データ群
    RefTable<matrix> depart_arrival;	// 発車後次列車到着まで
    RefTable<matrix> arrival_depart;	// 到着後次列車発車まで
    RefTable<matrix> arrival_arrival;	// 到着後次列車到着まで
    RefTable<matrix> depart_depart;		// 発車後次列車発車まで
    RefTable<matrix> depart_pass;		// 発車後次列車通過まで
    RefTable<matrix> arrival_pass;		// 到着後次列車通過まで
    RefTable<matrix> pass_arrival;		// 通過後次列車到着まで
    RefTable<matrix> pass_depart;		// 通過後次列車発車まで
    RefTable<matrix> pass_pass;		// 通過後次列車通過まで

    RefTable<from_station> warp_queue;	// 張付け待ち

    RefTable<bool> notrwtab;	// notrw が[i]の電車がいると true

  protected:
    RefTable<from_station> train_departure;	// 列車の発車データ

    void error26_name() {
	fprintf(stderr, "Error: subscript out of range in\n");
	fprintf(stderr, "       station_obj object to_station data call\n");
    }

    void arrv_dept_pass_table_set(RefTable<matrix>&);

    void rf_arrv_dept_pass_table(FILE*, RefTable<matrix>&, int);

  protected:

    void membercopy(const station_obj&);	// メンバコピー

    // 列車出発告知関係
    void this_train_will_depart_aaa(const train*) const;
    void this_train_will_depart_baa(const train*) const;

    // 拡張クラスのための readfile ユーティリティ
    virtual void readfile_additional_readfile(FILE* h, commandvalue x)
        {err_eof(h_file);}	// 拡張しない場合、この関数を呼ばれると異常
    virtual void readfile_additional_bool_set() {return;}
    virtual bool readfile_additional_bool_eval() {return true;}

    // 停車時分フラクチュエーションのための機構
    virtual void stationstop_variation_func
    (from_station& x, int i) {return;}
    
  public:

    station_obj();	// constructor
			// destructor は定義しない
    station_obj(const station_obj& x)
    : NoRefTable<to_station>(x) {}		// constructor: X(X&)
    station_obj& operator=(const station_obj&);	// 代入演算子

    int which_in_train_departure
    (const train*) const;	// train_departure の検索
  int which_in_to_station ( train const * ) const ;	// to_station の検索

    double outofstn_pos() const {return out_of_station;}
				// out_of_station を返す

    void remove(int);		// to_station の削除

    int readfile(FILE*);	// ファイルリード
    
    void set_stnno(int i) {stnno = i;}		// 駅番号セット
    int get_stnno() const {return stnno;}	// 駅番号を得る

    void from_station_init(const from_station) const;
				// 初期配置終了後 from_station を受け入れ
    void to_station_init(to_station) const;
				// 初期配置終了後 to_station を受け入れ

    bool voie_occupied(const train*) const;
		// to_station 配列中の列車が到着すべき番線が使用中: true

    void headway_cal_init();	// 時隔計算, 初期配置終了時に
    void headway_cal();		// 時隔計算

    bool do_not_depart(const train*) const;	// do_not_depart を返す

    virtual double tdept_delay(const train*) const;	// tdept_deley を返す
  virtual double tarr_delay ( train const * ) const ;	// tarr_deley を返す

    virtual void this_train_will_depart(const train*) const;	// 列車出発告知

    void from_station_generate(const train*) const;
	// to_station データを内部で from_station データに置き換え
    void from_station_warp(from_station) const;
	// from_station データを受けとりセット
};

#endif /* ! ___STNOBJ_HH */
