// 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.)
// train.hh --- header file that defines class train and related classes
// -----
// ChangeLog:
// 2010. 1. 22
//  Moved some global variables related to class traindata to the member
//  variables of class traindata.
// 2010. 1. 19
//  Removed tracf(). Created new member function getTractiveEffort() member
//  function in class train::_ParamFunc.
//  Removed sw_dtracf member variable.
// 2010. 1. 18
//  Moved ttvi_power() so it is now member of class train::_ParamFunc.
// 2010. 1. 17
//  Created train::_ParamFunc class. Moved ttvi_brake() so it is now the
//  member function of the new class.
// 2009. 11. 26
//  Added train::trn_ess member variable.
// 2008. 1. 18
//  Added train::writeToCSV(), train::writeHeaderToCSV() functions.
// -----

#include <cstdio>
#include <cstdlib>
#include <string>

#include "nextsta.hh"
#include "elecchar.hh"


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

using std :: string ;




// ----
// 列車運動に関するデータと関数
// 列車運動に関するデータと関数
// ----
class trainmotion
  : public elecchar
{

protected :
// 変数

  // 初期化後変更なし
  double rsc_ad ;	// 1.65
  double rsc_bd ;	// .0247
  double rsc_at ;	// .78
  double rsc_bt ;	// .028
  double rsc_cc ;	// .0358
  double rsc_cl ;	// .0078       : 走行抵抗係数(数字は通常時の値)
  double wdrivee ;	// 動力車自重
  double wloadd ;	// 動力車定員乗車時乗客荷重
  double wtraile ;	// 付随車自重
  double wloadt ;	// 付随車定員乗車時乗客荷重

  // 初期化後変更なし
  double cresist ;	// 曲線抵抗係数
  double wrotate ;	// 回転部等価質量係数
  double abh ;   	// 平坦直線減速度
  int setnum ;  	// 編成両数

  // プログラム中で変更
  double conges ;	// 混雑度

  // 力行時定数、conges にのみ依存→ setconges で変更
  double vlow_p ;	// 列車性能分界速度（低い方）
  double vhigh_p ;	// 列車性能分界速度（高い方）
  double constf_p ;	// 定トルク引張力
  double ampmax_p ;	// 最大電流

  // ブレーキ時定数、conges にのみ依存→ setconges で変更
  double vlow_b ;	// 列車性能分界速度（低い方）
  double vhigh_b ;	// 列車性能分界速度（高い方）
  double constf_b ;	// 定トルク引張力
  double ampmax_b ;	// 最大電流
  double ampmotor_b ;	// 最大モータ電流

  // 関数

public :

  trainmotion () {}	// empty constructor

  void setrsc ( double rscad , double rscbd , double rscat ,
                       double rscbt , double rsccc , double rsccl )
  { // 走行抵抗係数のセット
    rsc_ad = rscad ; rsc_bd = rscbd ; rsc_at = rscat ;
    rsc_bt = rscbt ; rsc_cc = rsccc ; rsc_cl = rsccl ;
  }

  void setweight ( double wd , double wld , double wt , double wlt )
  { // 車両自重・荷重値のセット
    wdrivee = wd ; wloadd = wld ; wtraile = wt ; wloadt = wlt ; }

  void setmres ( double cr , double wr , double ab , int stn )
  { // その他の定数のセット
    cresist = cr ; wrotate = wr ; abh = ab ; setnum = stn ;
  }

  double wall ( double cg )
  { return wdrivee + wtraile + cg * ( wloadd + wloadt ) ; }

  double wall () { return wall ( conges ) ; }	// 全重量

  double wdrive ( double cg ) { return wdrivee + cg * wloadd ; }
  double wdrive () { return wdrive ( conges ) ; }	// 動力車重量

  double wtrail ( double cg ) { return wtraile + cg * wloadt ; }
  double wtrail () { return wtrail ( conges ) ; }	// 付随車重量

  double eqrot () ;		// 回転部等価質量係数

} ;

struct pbchar
{
  double conges ;	// 混雑率 (％表示ではない )
  double mcurr ;	// 最大電流
  double lowvel ;	// 定電力領域下限速度
  double highvel ;	// 定電力領域上限速度
  double tracf ;	// 定トルク領域引張力（tf）
  double motorcurr ;	// モータ電流 (A )
} ;


// 力行時データ
struct powerdata
{
  pbchar pbempty ;
  pbchar pbmid ;
  pbchar pbfull ;	// データの主要部分（空車・中間・最大乗車時）
  double ec ;		// 電車線電圧
  double zerocur ;	// 0 km/h 時の電流値
  double minvol ;	// 最低電圧
  double bminvol ;	// 常用最低電圧
  double maxvol ;	// 最高電圧
} ;


// 回生時データ
struct brakedata
{
  pbchar pbempty ;
  pbchar pbmid ;
  pbchar pbfull ;	// データの主要部分（空車・中間・最大乗車時）
  double ec ;		// 電車線電圧
  double regenoff ;	// 回生オフ速度
  double minvol ;	// 最低電圧
  double bminvol ;	// 常用最低電圧
  double maxvol ;	// 最高電圧
  double startvol ;	// 絞り込み開始電圧
  double regendvol ;	// 絞り込み終了電圧
  double regendantei ;	// 絞り込み終了後の安定化のための電流値
} ;


// rnotch 自動制御用データ
struct autodata
{
  double minvel ;  	// 力行電流制限開始速度
  double fullvel ; 	// 力行電流制限フル実行開始速度
  double pminvol ; 	// 力行電流制限開始電圧(V2 )
  double poffvol ; 	// 力行電流０となる速度(V1 )
  double pminvolx ; 	// V2 の初期値
  double poffvolx ; 	// V1 の初期値
  double crbvol ;  	// 惰行時力行をはじめる電圧(V3 )
  double crfvol ;  	// 惰行時力行フルとなる電圧(V4 )
} ;


// ----
// Forward declaration of class ESS_OnBoard
// class ESS_OnBoard の forward declaration
// ----
class ESS_OnBoard ;



// 列車データの読み込み用クラス
class traindata
  : public readdata
{

public :	// 全部公開のクラス、実は struct と同じ

  cs_command ccx ;	// ピークカット制御のコントロールフラグ
  powerdata p ;		// 力行データ群
  brakedata b ;		// 力行データ群
  autodata a ;		// ピークカット制御用データ群、通常は意味がない
  double cong ;		// 混雑率
  double auxcurr ;	// 補機電流，電流一定モデリング
  double wta ;		// M車重量
  double wtb ;		// M車荷重
  double wtc ;		// T車重量
  double wtd ;		// T車荷重
  double rca , rcb , rcc , rcd , rce , rcf ;	// 走行抵抗係数
  double mra ;		// 曲線抵抗係数
  double mrb ;		// 回転部等価質量係数
  double mrc ;		// 平坦線減速度
  int mrd ;		// 編成両数

  // ----
  // On-board energy storage system model.
  // 車載エネルギー蓄積装置モデル。
  // ----
  ESS_OnBoard * _ess ;

  //********************************************************************//
  // Variables that used to be "global" and were defined in globvar.hh. //
  // 以前は globvar.hh にあった「グローバル変数」.                      //
  //********************************************************************//

  // ----
  // If true, give maximum system voltage independent of the regeneration
  // limiter high threshold voltage. Not referred in any other classes.
  // 回生絞り込み終了電圧が最高電圧と異なる場合 true. 他のクラスでは参照さ
  // れていない。
  // ----
  bool sw_different_regend ;

  // ----
  // If true, auxiliary load level is specified in kilowatt rather than
  // ampere. Referred in train::ttvi_auxcurr() member function.
  // これが true のとき，補機電力は A でなく kW で与えられる。Class train の
  // メンバ関数 train::ttvi_auxcurr() で参照されている。
  // ----
  bool sw_aux_power ;

  // ----
  // If true, use motor current to decide whether to activate regeneration
  // limiter. Referred in train::ttvi_brake() member function.
  // これが true のとき，回生絞込を行うか否かをモータ電流で判別する。
  // Class train のメンバ関数 train::ttvi_brake() で参照されている。
  // ----
  bool sw_torque_shibori ;

  // ----
  // If true, use INFERIOR regeneration limiter characteristics (especially
  // when the payload weight is small). Referred to in train::ttvi_brake().
  // これが true のとき，特に荷重が小さいときに性能が低くなる回生絞込特性を
  // 用いる。Class train のメンバ関数 train::ttvi_brake() で参照されている。
  // ----
  bool sw_shibori_parallel ;

  // ----
  // If true, distinguish "regeneration limiting" and "regeneration failure".
  // If false, the latter is the special case of the former, i.e. regenerated
  // power is zero because of the limiter. Referred to in train::ttvi_brake().
  // これが true のとき，回生絞込と回生失効を区別する。false の場合，後者は単
  // に前者の特殊な場合（回生パワーがゼロまで絞り込まれた状態）にすぎなくなる。
  // Class train のメンバ関数 train::ttvi_brake() で参照されている。
  // ----
  bool sw_regenoffantei ;

  // ----
  // If true, whether regeneration fails is determined based on traction
  // motor current rather than the pantograph current. Referred to in
  // train::regendead().
  // これが true のとき，回生絞込するかどうかはパンタ点電流ではなくモータ
  // 電流にて判定される。関数 train::regendead() で参照されている。
  // ----
  bool sw_anteimotor ;

  //********************************************************************//
  // Functions                                                          //
  // 関数                                                               //
  //********************************************************************//

  void readfile ( FILE * , char * ) ;	// ファイルリード

  // ----
  // Reading the XML-style input file.
  // XMLファイルリード。
  // ----
  void readfile_xml ( TiXmlNode const * , string const & ) ;

  // Constructor
  traindata ()
    : cong ( 0 ) , auxcurr ( 0 ) , wta ( 0 ) , wtb ( 0 ) , wtc ( 0 ) ,
      wtd ( 0 ) , rca ( 0 ) , rcb ( 0 ) , rcc ( 0 ) , rcd ( 0 ) , rce ( 0 ) ,
      rcf ( 0 ) , mra ( 0 ) , mrb ( 0 ) , mrc ( 0 ) , mrd ( 0 ) ,
      _ess ( 0 ) , sw_different_regend ( false ) , sw_aux_power ( false ) ,
      sw_torque_shibori ( false ) , sw_shibori_parallel ( false ) ,
      sw_regenoffantei ( false ) , sw_anteimotor ( false )
  { _ess = new No_ESS_OnBoard ; }

} ;



// ----
// Object in which parameter functions for a train are to be calculated.
// 列車のための媒介変数利用関数の演算.
// ----
class train_ParamFunc
{
private :

  // ----
  // Well, this kind of thing might be useful...
  // まあ，こういうのもあったほうがいいでしょう…
  // ----
  int __carno ;		// 車両番号: (= csno - nss )

  // ----
  // Regenerative performance parameters.
  // 電力回生データ.
  // ----
  brakedata __bd ;

  // ----
  // Acceleration performance parameters.
  // 力行性能データ.
  // ----
  powerdata __pd ;
    
  // ----
  // Braking performance parameters.
  // ブレーキ時性能パラメータ.
  // ----
  double __vlow_b ;	// 列車性能分界速度（低い方）
  double __vhigh_b ;	// 列車性能分界速度（高い方）
  double __constf_b ;	// 定トルク引張力
  double __ampmax_b ;	// 最大電流
  double __ampmotor_b ;	// 最大モータ電流

  // ----
  // Powering performance parameters.
  // 力行時性能パラメータ.
  // ----
  double __vlow_p ;	// 列車性能分界速度（低い方）
  double __vhigh_p ;	// 列車性能分界速度（高い方）
  double __constf_p ;	// 定トルク引張力
  double __ampmax_p ;	// 最大電流

  // ----
  // Parameters used by member function ttvi_brake().
  // メンバ関数 ttvi_brake() が利用するパラメータ.
  // ----
  double __pos ;
  double __vel ;
  double __tt ;
  double __v ;
  double __dv ;
  double __rnotch ;
  double __rnotch_for_capper ;
  double __a ;
  double __a_wo_capper ;
  double __a_main_circuit ;
  double __di ;
  double __noshibo ;
  double __dnch ;
  bool __sw_regendead ;
  bool __is_limiting_regen ;
  // bool __emccal ;
  // double __emrn ;

  // ----
  // Pointer to an on-board energy storage system.
  // 車載エネルギー蓄積装置へのポインタ。
  // ----
  ESS_OnBoard * trn_ess ;

  // ----
  // Maximum tractive and braking effort. Calculated by the member function
  // prepareMaximumEffort(). Note that in function getMaxBrakingEffort(),
  // the sign of __max_braking_effort is reversed when returning the value.
  // 最大牽引力・ブレーキ力。メンバ関数 prepareMaximumEffort() により計算
  // される。getMaxBrakingEffort() 関数では __max_braking_effort の値の符号
  // が反転されることに注意。
  // ----
  double __max_tractive_effort ;
  double __max_braking_effort ;

  // ----
  // If true, use motor current to decide whether to activate regeneration
  // limiter. Used to be g_sw_torque_shibori in globvar.hh.
  // これが true のとき，回生絞込を行うか否かをモータ電流で判別する。
  // かつては globvar.hh で g_sw_torque_shibori として定義されていた。
  // ----
  bool __sw_torque_shibori ;

  // ----
  // If true, use INFERIOR regeneration limiter characteristics.
  // Used to be g_sw_shibori_parallel in globvar.hh.
  // これが true のとき，特に荷重が小さいときに性能が低くなる回生絞込特性を用
  // いる。かつて globvar.hh で g_sw_shibori_parallel として定義されていた。
  // ----
  bool __sw_shibori_parallel ;

  // ----
  // If true, distinguish "regeneration limiting" and "regeneration
  // failure". If false, the latter is the special case of the former, i.e.
  // regenerated power is zero because of the limiter. Used to be
  // g_sw_regenoffantei in globvar.hh.
  // これが true のとき，回生絞込と回生失効を区別する。false の場合，後者は
  // 単に前者の特殊な場合（回生パワーがゼロまで絞り込まれた状態）にすぎなく
  // なる。かつて globvar.hh で g_sw_regenoffantei として定義されていた。
  // ----
  bool __sw_regenoffantei ;

  // ----
  // Pointer to an nextsta data.
  // nextsta データ（次駅データ）へのポインタ。
  // ----
  nextsta const * __nxx ;

public :

  // Constructor 
  explicit train_ParamFunc
  ( int __carno_in , brakedata const & __bd_in , powerdata const & __pd_in ,
    double __vlow_b_in , double __vhigh_b_in , double __constf_b_in ,
    double __ampmax_b_in , double __ampmotor_b_in , double __vlow_p_in ,
    double __vhigh_p_in , double __constf_p_in , double __ampmax_p_in ,
    double __pos_in , double __vel_in , double __tt_in ,
    double __v_in ,			double __dv_in ,
    double __rnotch_in , double __dnch_in , double __rnotch_for_capper_in ,
    double __a_in ,			double __a_wo_capper_in ,
    double __a_main_circuit_in , double __di_in , double __noshibo_in ,
    bool __sw_regendead_in ,		bool __is_limiting_regen_in ,
    bool __sw_torque_shibori_in ,	bool __sw_shibori_parallel_in ,
    bool __sw_regenoffantei_in ,	ESS_OnBoard * trn_ess_in ,
    nextsta const * __nxx_in ) ;

  // Copy constructor
  explicit train_ParamFunc ( train_ParamFunc const & ) ;

  // Destructor
  ~train_ParamFunc () { if ( trn_ess ) delete trn_ess ; }

  // ----
  // Subprograms of teta_vi().
  // teta_vi() のサブプログラム.
  // ----
  void ttvi_brake () ;
  void ttvi_power () ;
  void ttvi_RegenLimiter () ;

  // ----
  // Routine around the energy storage system
  // エネルギー蓄積装置がらみの処理.
  // ----
  void ttvi_ess () ;

  // ----
  // Functions related to the calculation of tractive and braking effort.
  // 牽引力・ブレーキ力計算関連の関数.
  // ----
  void prepareMaximumEffort () ;
  double getTractiveEffort () const ;

  // ----
  // Setting variables.
  // 変数をセットする。
  // ----
  void setVelocity ( double x ) { __vel = x ; }
  void setVoltage ( double x ) { __v = x ; }
  void setNotchRate ( double x ) { __rnotch = x ; }
  void setCurrent ( double x ) { __a = x ; }
  void setCurrentWithoutLimiter ( double x ) { __noshibo = x ; }
  void set_Di_Dtheta ( double x ) { __di = x ; }
  void setCurrentWithoutCapper () { __a_wo_capper = __a ; }
  void setMainCircuitCurrent ( double x ) { __a_main_circuit = x ; }
  void setMainCircuitCurrent () { __a_main_circuit = __a ; }
  void setNotchRateForCapper ( double x ) { __rnotch_for_capper = x ; }
  
  // ----
  // Getting data and results.
  // データや結果を得る。
  // ----
  nextsta const * getNextsta () const { return __nxx ; }
  int getCarNumber () const { return __carno ; }
  double getVoltage () const { return __v ; }
  double get_dV_dTheta () const { return __dv ; }
  double getCurrent () const { return __a ; }
  double get_Di_Dtheta () const { return __di ; }
  double getCurrentWithoutLimiter () const { return __noshibo ; }
  double getCurrentWithoutCapper () const { return __a_wo_capper ; }
  double getMainCircuitCurrent () const { return __a_main_circuit ; }
  double getNotchRateForCapper () const { return __rnotch_for_capper ; }
  bool isLimitingRegen () const { return __is_limiting_regen ; }
  double getMaxTractiveEffort () const { return __max_tractive_effort ; }
  double getMaxBrakingEffort () const { return - __max_braking_effort ; }
  double getPosition () const { return __pos ; }
  double getVelocity () const { return __vel ; }
  ESS_OnBoard const & getESS () const { return * trn_ess ; }  

private :

  // ----
  // Routine around the energy storage system
  // エネルギー蓄積装置がらみの処理.
  // ----
  void ttvi_ess_ProcessRegenLimiter () ;

  // ----
  // Regeneration "taper" characteristics.
  // 回生絞込特性.
  // ----
  double ttvi_brake_shibori ( double , double , double , double ) const ;

  // ttvi_power の subpr.
  void tv_p_ne ( double , double , double , double , double ) ;

  // tv_p_ne/em の subpr.
  void tv_p_tc ( double & , double , double , double ) ;
  double tv_p_tc ( double & , double , double ) const ;
} ;



// 列車データと関数
class train
  : public trainmotion
{

  // 変数
  bool ontprec ;	// ontime サブルーチンが最後まで到達したら true
  bool cpsww ;  	// 惰行中に rnotch != 0 となったら true
  bool cpsw ;   	// 惰行中に一度でも cpsww == true となったら true
//	int rntrans ;	// rnotch が変化中だと絶対値 1 符号は変化の方向
  // bool emccal ; 	// ccal が正常終了しないと true
  // double emrn ; 	// ccal が正常終了しないときのノッチ比
  double lenrun ;	// この駅間に入るまでにすでに走った距離の総和
  double stpos ;	// 走りはじめ位置……走行距離を求めるのに用いる
  bool b_jerk ; 	// ジャークコントロールオンのとき true
  int ssno ;    	// 起点側変電所番号
  double sis ;  	// 起点側変電所までのインピーダンス
  bool nosss ;  	// 起点側に変電所なし、のとき true
  double iss ;  	// 起点側変電所電流推定値
  int seno ;    	// 終点側変電所番号
  double sie ;  	// 終点側変電所までのインピーダンス
  bool nosse ;  	// 終点側に変電所なし、のとき true
  double ise ;  	// 終点側変電所電流推定値
  bool signal_changed ; // 信号現示変化時 true
  bool sigchange_repower ;  	// 信号現示変化後の再力行時 true
  double tarr_real ;	// 駅到着時刻実績値
  double a_max_regen ;	// 回生絞込なしと仮定した場合の電流（補機含む）

  // 変電所特性データ、初期化以後変更なし
  sschar * sc ; 	// 変電所データ
  int nss ;     	// 変電所数
//	double ccv ;		// Cc （変電所電流）
//	double clv ;		// Cl （変電所電流）
  double prate ;	// 力行率
  double ptime ;	// 力行時間
  int pfirst ;		// 初力行 0, 以降力行/回生のみ終了時 increment
  double dtracf ;	// tracf の微分値
//   bool sw_dtracf ;	// tracf が回生絞り込みを考慮しないとき true
  double zerovolt ;	// 回生電流ゼロとなる電圧
  bool sw_regendead ;	// 回生失効中のとき true

  // ----
  // Pointer to an on-board energy storage system.
  // 車載エネルギー蓄積装置へのポインタ。
  // ----
  ESS_OnBoard * trn_ess ;

  // -----
  // If true then suppress output to CSV file.
  // もし真なら CSV ファイルへの出力を抑制する。
  // -----
  bool suppress_csv ;

protected :

  // 定数、初期化以後変更なし
  int carno ;	// 車両番号: (= csno - nss )
  double auxcurr ;		// 補機電流，電流一定モデリング

  // ----
  // Train type key. Given to feeder::_trd map to get the necessary traindata.
  // 車両形式キー文字列。これを feeder::_trd マップに渡し，必要な traindata
  // を得る。
  // ----
  string const * train_type_key ;

  // ----
  // If true, auxiliary load level is specified in kilowatt rather than
  // ampere. Used to be g_sw_aux_power in globvar.hh.
  // これが true のとき，補機電力は A でなく kW で与えられる。かつては
  // globvar.hh で g_sw_aux_power として定義されていたもの。
  // ----
  bool sw_aux_power ;

  // 列車特性データ、初期化以後変更なし
  powerdata pdata ;	// 力行特性データ
  brakedata bdata ;	// 回生特性データ
  autodata adata ; 	// rnotch 自動制御用データ

  // 初期値を与えるもの
  nextsta const * nxx ;	// 次駅データ
  double pos ; 	// 列車位置
  double vel ; 	// 列車速度
  car_stat stat ;	// 列車状態
  car_stat stat_old ;	// stat の古い値
  double tdept ;	// 駅出発時刻
  double taudx ;	// 駅出発時遅れ
  //     double taudx_delay ;	// 前区間で遅れるべき時分に対する遅れ

  // 計算により求めるもの
  double cmd_aux ;	// 補機指令値
  double rnotch ;	// 電流／トルクのフルノッチ比（-1 〜 1）
  double dnch ;	// フルノッチ比の変化率 dr/dθ（θ=tt）

  // ----
  // If true, calculate mechanical acceleration / deceleration power.
  // True であれば機械的加減速パワーを計算する。
  // ----
  bool _sw_mech_power ;

  // ----
  // Mechanical acceleration / deceleration power. _mech_power_motor_ratio
  // shows the ratio (0 - 1) of _mech_power provided by electric braking.
  // ----
  double _mech_power ;
  double _mech_power_motor_ratio ;

  // ----
  // Full-notch ratio when current capper is in operation. Range: 0 - 1.
  // Current capper が働いた場合のフルノッチ比. 0 - 1.
  // ----
  double rnotch_for_capper ;
  
  double rnotchold ;	// rnotch の古い値

  // nxx->dpgrad で定まる勾配データの配列上の位置
  nextsta :: gc_size_type pgrad ;

  station_obj const * stnobj_now ;	// 現在関係中の station_obj を指す
  double a_wo_capper ;	// Current capper がないときの電流
  double a_main_circuit ;	// 主回路電流
  double noshibo ;	// 絞り込みなしの電流
  double shibo ;	// 絞り込みありの電流
  double shibo_old ;	// 絞り込みありの電流、古い値
  double brakev ;	// ブレーキ時の目標速度
  bool iamconst ;	// ブレーキオフ後定速状態で走行するとき true
  bool iamcoast ;	// 定速状態は下り坂のみで使用するとき true
  bool sw_btws ;	// 駅間停止のためのブレーキ時 true
  bool sw_x_btws ;	// 駅間停止位置を過ぎていない場合 true
  bool is_limiting_regen ;	// 回生絞り込み中だと true
  bool is_limiting_max_curr ;	// 最大電流絞込み中だと true

  // ----
  // If true, use motor current to decide whether to activate regeneration
  // limiter. Used to be g_sw_torque_shibori in globvar.hh.
  // これが true のとき，回生絞込を行うか否かをモータ電流で判別する。
  // かつては globvar.hh で g_sw_torque_shibori として定義されていた。
  // ----
  bool sw_torque_shibori ;

  // ----
  // If true, use INFERIOR regeneration limiter characteristics.
  // Used to be g_sw_shibori_parallel in globvar.hh.
  // これが true のとき，特に荷重が小さいときに性能が低くなる回生絞込特性を用
  // いる。かつて globvar.hh で g_sw_shibori_parallel として定義されていた。
  // ----
  bool sw_shibori_parallel ;

  // ----
  // If true, distinguish "regeneration limiting" and "regeneration failure".
  // If false, the latter is the special case of the former, i.e. regenerated
  // power is zero because of the limiter. Used to be g_sw_regenoffantei in
  // globvar.hh.
  // これが true のとき，回生絞込と回生失効を区別する。false の場合，後者は単
  // に前者の特殊な場合（回生パワーがゼロまで絞り込まれた状態）にすぎなくなる。
  // かつて globvar.hh で g_sw_regenoffantei として定義されていた。
  // ----
  bool sw_regenoffantei ;

  // ----
  // If true, whether regeneration fails is determined based on traction
  // motor current rather than the pantograph current. Used to be
  // g_sw_anteimotor in globvar.hh.
  // これが true のとき，回生絞込するかどうかはパンタ点電流ではなくモータ
  // 電流にて判定される。かつて globvar.hh で g_sw_anteimotor として定義。
  // ----
  bool sw_anteimotor ;

public :

// 関数

private :

  // ontime 関数用サブプログラム

  // ブレーキ終了位置からの逆算
  // 引数: arv, arp, k, pos, j, vp, bt
  void brake ( double , double , nextsta :: gc_size_type , double ,
               nextsta :: gc_size_type , double & , double & ) ;

  // ブレーキ開始位置の決定
  void pbx ( double , double , double , double , double , double , double & ,
	     double & , bool & , double & , double & ) ;
  void pbx ( double , double , double , double , double , double , double & ,
	     double & , bool & ) ;
             	// 引数: av , v , ap , p , ab , a , t , vb , sw

  // 定加速度運動中の列車の運動の計算
  // 引数: v, a, lg, t, vr, sw
  void cavt ( double , double , double , double & , double & , bool & ) ;

  bool ontvlim ( double , nextsta :: gc_size_type , double , double & ,
                 nextsta :: gc_size_type & , double & ) ;
  void ontvlc ( double , nextsta :: gc_size_type , double , double ,
                double & , nextsta :: gc_size_type & , double & , double & ,
                double , nextsta :: gc_size_type , double , bool = false ) ;
  void ontconst ( double & ) ;
  void ontcm ( double & , nextsta :: gc_size_type & , double & , double & ,
               double & , double & , double & ) ;
  void ontctoc ( double , double & , nextsta :: gc_size_type , double & ,
                 double & , double & , double & , double & ) ; 
  double ontbrake ( double , nextsta :: gc_size_type , double , double ) ;
  double ontbc ( double , nextsta :: gc_size_type , double , double ) ; 


  // nextmotion 用サブプログラム

  double ontimesub ( double , int , double , double ) ;
  double tresist ( double x , nextsta :: gc_size_type i )
  { return tresist ( x ) + gresist ( i ) ; }	// 全列車抵抗

  void nm_power ( double ) ;	// 力行中の次状態演算
  void nm_coast ( double ) ;	// 惰行中の次状態演算
  void nm_regen ( double ) ;	// 回生のみ中の次状態演算
  void nm_brake ( double ) ;	// ブレーキ中の次状態演算
  void nm_stnstop ( double ) ;	// 駅停車中の次状態演算
  void nm_constv ( double ) ;	// 定速走行中の次状態演算
  bool nm_nxxps () ;		// nm_constv () , nm_coast () のサブルーチン
  void nm_stnbtws ( double ) ;	// 駅間停止中の次状態演算

  bool vlimitbrake () ;		// 前方制限速度の検知→ブレーキ処理
  bool nm_stnobj_brake () ;	// 信号系の指令変化→早着→ブレーキ処理
  bool nm_stnobj_power () ;	// 信号系の指令変化→遅着→加速処理


  // teta_vi 特性プログラム用サブプログラム

  void tetavisub ( double ) ;	// 引数: rnotch
  void vset ( double ) ;	// 電圧値のセット、tetavisub の subprogram
  void ttvi_power () ;	// teta_vi の subprogram

  // ----
  // ttvi_brake() is now member of train_ParamFunc subclass. This function
  // creates one instance of train_ParamFunc, execute ttvi_brake() , then delete
  // the instance.
  // ttvi_brake() は子クラス train_ParamFunc のメンバ関数に移動。この関数は，
  // train_ParamFunc のインスタンスを生成，ttvi_brake() を実行後当該インスタンスを
  // 破棄する。
  // ----
  void ttvi_brake () ;

  // 補機電流の計算
  void ttvi_auxcurr () ;

  // ----
  // Routine around the energy storage system
  // エネルギー蓄積装置がらみの処理.
  // ----
  void ttvi_ess () ;

  // ----
  // Construction of an instance of the teta_vi calculator class
  // teta_vi 計算用クラスインスタンスの生成
  // ----
  train_ParamFunc * getNewParamFuncCalculator () const
  { return new train_ParamFunc
      ( carno , bdata , pdata , vlow_b , vhigh_b , constf_b , ampmax_b ,
        ampmotor_b , vlow_p , vhigh_p , constf_p , ampmax_p ,
        pos , vel , tt , v , dv , rnotch , dnch , rnotch_for_capper ,
        a , a_wo_capper , a_main_circuit , di , noshibo ,
        sw_regendead , is_limiting_regen , sw_torque_shibori ,
        sw_shibori_parallel , sw_regenoffantei , trn_ess , nxx ) ; }

  // 従来の線形応荷重補間方式
  double cgdef ( double , double ) ;	// cg の計算
  double cgcal ( double , double , double ) ;	// cg による計算


  // インバータ定トルク<->フリーラン突合せ時応荷重補間方式
  double velcal_mid
  ( double , double , double , double , double , double ) ;	//応荷重速度
  double ampcal_mid
  ( double , double , double , double , double , double ) ;	//応荷重速度



  // notchrate の subprogram

  // 力行時
  void nr_power ( double & , double & ) ;		// 引数: rnotch, dnch
  void nr_power () { nr_power ( rnotch , dnch ) ; }
  void nr_regen () ;	// 回生時
  void nr_coast () ;	// 惰行時
  void nr_constv () ;	// 定速走行時
  void nr_p_ea ( double & , double & ) ; 	// ccmd = Ecauto、力行時
  void nr_c_ea () ; 	// ccmd = Ecauto、惰行時

  to_station to_station_emit () ;	// to_station オブジェクトを生成
  from_station from_station_emit () ;	// from_station オブジェクトを生成

  double tdept_delay () ;	// 列車の出発時間の遅れ分

  train ( const train & ) ;         	// constructor: X ( X & ) 禁止
  train & operator= ( train & ) ; 	// 代入禁止
  explicit train () ;	// empty constructor

public :
  train ( string const * ) ;	// empty constructor
  ~train () ;                   	// destructor

  // sc 配列（車両が持つ変電所データ）の領域確保
  void newsc ( int x ) { nss = x ; sc = new sschar [ x ] ; }

  double tresist ( double ) ; 	// 列車の走行抵抗（引数: vel）

  bool getSuppressCSVFlag () const { return suppress_csv ; }


  // ブレーキオフ位置計算

  // 引数 pos, pgrad, vel, arv
  double bklen ( double , nextsta :: gc_size_type , double , double ) ;

  // 引数 pos, pgrad, vel
  double bklen
  ( double bkpos , nextsta :: gc_size_type jgrad , double bkvel )
  { return bklen ( bkpos , jgrad , bkvel , nxx -> varrive () ) ; }

  // 引数 nxx->varrive ()
  double bklen ( double varr )
  { return bklen ( pos , pgrad , vel , varr ) ; }

  // 引数なし
  double bklen () { return bklen ( nxx -> varrive () ) ; }



  // 列車走行シミュレーション

  // ----
  // Disable or enable mechanical power calculation.
  // 機械的パワーの計算を抑制もしくは許可する。
  // ----
  void disableMechanicalPowerCalculation () { _sw_mech_power = false ; }
  void enableMechanicalPowerCalculation () { _sw_mech_power = true ; }

  // 引数 pos, pgrad, vel, tracf
  void npos ( double & , nextsta :: gc_size_type & , double & , double = 0 ) ;

  // 引数 tracf
  void npos ( double tracff = 0 )
  { npos ( pos , pgrad , vel , tracff ) ; }

  // ブレーキ時、引数 pos, pgrad, vel, tracff
  void nposb ( double & , nextsta :: gc_size_type & , double & , double = 0 ) ;

  // ブレーキ時、引数 tracff
  void nposb ( double tracff = 0 ) { nposb ( pos , pgrad , vel , tracff ) ; }

  // 定速走行時、引数 pos, pgrad, vel, tracff
  void nposc ( double & , nextsta :: gc_size_type & , double & , double = 0 ) ;

  // 定速走行時、引数なし
  void nposc ( double tracff = 0 ) { nposc ( pos , pgrad , vel , tracff ) ; }

  double brakef () ;	// 所要ブレーキ力（tf）、正値を返す
  double brakef ( double ) ;	// 所要ブレーキ力（tf）、正値を返す

  // 牽引力、ブレーキ力は負値を返す
  double getTractiveEffort () const ;
  // ----
  // There used to be a "double tracf (double, double, double = -1)" function
  // here. Three arguments were velocity, voltage and notchrate.
  // ----
  

  // 定時ノッチオフ制御 ( _prec は精度向上版 )
  double ontime_prec ( double , nextsta :: gc_size_type , double , double ) ;
  double ontime_prec ( double t ) {
    return ontime_prec ( pos , pgrad , vel , t ) ;
  }
  double ontime ( double , nextsta :: gc_size_type , double , double ) ;
  double ontime ( double t ) {return ontime ( pos , pgrad , vel , t ) ;}


  // 列車の勾配抵抗（tf）、引数: pgrad
  double gresist ( nextsta :: gc_size_type jgrad )
  { return egrad ( jgrad ) * wall () / 1000 ; }

  // 列車の勾配抵抗（tf）、引数: pos
  double gresist ( double grpos )
  { return egrad ( grpos ) * wall () / 1000 ; }
		
  // 列車の勾配抵抗（tf）、引数: なし
  double gresist ()
  { return train :: gresist ( pgrad ) ; }
       	
  double egrad ( nextsta :: gc_size_type ) ;   	// 等価勾配（引数: pgrad）
  double egrad ( double ) ; 	// 等価勾配（引数: pos）


  // 走った距離
  double runlen () { return lenrun + ( pos - stpos ) * direc () ; }
  void addlen ()
  { lenrun += ( nxx -> parrive () - stpos ) * direc () ; }


  // 列車の次状態の計算
  void nextmotion ( double ) ;

  void teta_vi () ; 	// teta から volt , ampere へ
  void add_to_teta ( double , bool ) ;	// teta に加える
  void notchrate () ; 	// フルノッチ比の計算
  void autodreg () ;	// autodata の自動修正 ( Ea_cvauto0 モード用 )


  // 回生失効判定関数
  // 引数：なし / ddhh, tregendead ( simulate.cc で定義 )
  bool regendead () { return sw_regendead ; }	// sw_regendead を単に返す
  void regendead ( double , double & ) ;

  // 現在の回生絞り込み率
  double regenrate () const ;

  // 回生絞込がなかったと仮定した場合の電流値を返す
  double getCurrentWithoutRegenLimiter () const { return a_max_regen ; }
  double getNotchRateForCapper () const { return rnotch_for_capper ; }

  // Getting most recent "mechanical power".
  double getMechanicalPower () const { return _mech_power ; }
  double getRatioOfElectricEffortInMechPower () const
  { return _mech_power_motor_ratio ; }

  void setconges ( double ) ;	// 混雑率セット ,混雑率のみ依存の係数計算

  // ----
  // Setting on-board ESS module.
  // 車載エネルギー蓄積装置モデルの組み込み。
  // ----
  void setOBESS ( ESS_OnBoard * x ) { trn_ess = x -> getMyClone () ; }

  // -----
  // Calculate voltage and current of the ESD.
  // -----
  void calculateESDVoltageAndCurrent () ;

  // -----
  // Renew the electrical state variables. Does nothing here.
  // 電気的状態変数を更新。ここではなにもしない。
  // -----
  void renewElectricalStates () ;

  // -----
  // SOC-related initialisation upon start of the simulation cycle.
  // -----
  void setStartSOC () { trn_ess -> setStartSOC () ; }

  // -----
  // Typing out SOC-related data to the RES file.
  // -----
  void printSOCStoredResults
  ( ostream & x , ostringstream & y , ostringstream & z ) const
  { trn_ess -> printSOCStoredResults ( x , y , z ) ; }

  // -----
  // Output to CSV file. Boolean argument: suppress leading comma if false.
  // CSVファイルへの出力. 論理値引数: 偽ならカンマの出力を抑制
  // -----
  bool writeHeaderToCSV ( ostream & , bool = true ) const ;
  bool writeToCSV ( ostream & , bool = true ) const ;

  double & gva () { return a ; }	// 既知側変数（電流）
  double & uva () { return v ; }	// 未知側変数（電圧）
  double & dgva () { return di ; }	// 既知側差分値（電流）
  double & duva () { return dv ; }	// 未知側差分値（電圧）

  // 回生絞り込み中だと true を返す関数
  bool isLimitingRegen () const { return is_limiting_regen ; }

  // 最大電流絞り込み中だと true を返す関数
  bool isLimitingMaxCurrent () const { return is_limiting_max_curr ; }

  // 最大電流絞り込み中フラグをセット／アンセットする関数
  void setMaxCurrentLimitFlag () { is_limiting_max_curr = true ; }
  void unsetMaxCurrentLimitFlag () { is_limiting_max_curr = false ; }

  // 回生絞り込み終了電圧と開始電圧の差の nrtw 分の1
  double getRegenTaperWidth ( int nrtw ) const
  {
    if ( nrtw <= 0 )
    {
      cerr << "Error: positive integer must be given to "
           << "train::getRegenTaperWidth ()" << endl ;
      exit ( 81 ) ;
    }
    return ( bdata . regendvol - bdata . startvol ) / nrtw ;
  }

  // bool & emgc () { return emccal ; }		// emccal への参照
  double asibori () const { return noshibo ; }	// 絞込みなしの I
  double sibori () const { return shibo ; }	// 絞込みありの I
  double position () const { return pos ; } 	// 位置
  double velocity () const { return vel ; } 	// 速度
  double cc () const { return ccv ; }		// Cc
  double cl () const { return clv ; }		// Cl
  cs_command ccommand () const { return ccmd ; }	// ccmd
  car_stat carstat () const { return stat ; }	// 列車状態
  car_stat carstold () const { return stat_old ; }	// 直前の列車状態
  double rnotchvl () const { return rnotch ; }	// フルノッチ比
  double drnotchvl () const { return dnch ; }
  bool noss () const { return nosss ; }  	// 起終点側に変電所が
  bool nose () const { return nosse ; }  	// なければ true を返す
  int ssnum () const { return ssno ; }  	// 起点側変電所番号を返す
  int esnum () const { return seno ; }  	// 終点側変電所番号を返す
  double isss () const { return iss ; }		// 起点側変電所電流推定値
  double isse () const { return ise ; }		// 終点側変電所電流推定値
  nextsta const * NextSta () { return nxx ; }
  int nfline () const { return nxx -> feedlinenumber () ; }	// 饋電線番号
  int direc () const { return nxx -> direction () ; }	// 列車方向
  nextsta :: gc_size_type gradnumber () const
  { return pgrad ; }	// 列車方向
  feedpos & feep () {		// Ｙ行列作成用データを返す
    static feedpos x ;
    x . pos = pos ; x . csno = csno ; x . sttimp = x . endimp = 0.0 ;
    return x ;
  }
  void setsc ( sschar x , int i ) { sc [ i ] = x ; }
  void setsc ( int i , sschar x ) { sc [ i ] = x ; }	// sschar 変数の代入
  void zlenrun () { lenrun = 0.0 ; }	// lenrun のリセット
  void setstpos () { stpos = pos ; }	// stpos のセット
  void resettd ( double t ) {	// tdept , tarr_real のリセット
    tdept -= t ;	tarr_real -= t ;
  }
  void setstatold ( car_stat x ) { stat_old = x ; }
  void dist_iamconstcoast ( FILE * td )
  { fprintf ( td , "iamconstcoast %i %i\n" , iamconst , iamcoast ) ; }
  void diststatold ( FILE * td ) 
  { fprintf ( td , "setstatold %i\n" , stat_old ) ; }
  void set_iamconstcoast ( bool cn , bool ca )
  { iamconst = cn ; iamcoast = ca ; }
  void setstatold () { setstatold ( stat ) ; }	// stat_old のセット
  void setcmdaux ( double caux ) { cmd_aux = caux ; }	// 代入用

  // ----
  // Setting auxiliary load data.
  // 補機負荷データをセットする。
  // ----
  void setAuxiliaryLoad ( double x , bool sw )
  { auxcurr = x ; sw_aux_power = sw ; }

  // ----
  // Setting "shibori" flags (determine how regeneration limiter will work).
  // "shibori" フラグのセット（回生絞込機構の動作を定める）
  // ----
  void setShiboriFlags ( bool _ts , bool _sp , bool _ro , bool _am )
  { sw_torque_shibori = _ts ; sw_shibori_parallel = _sp ;
    sw_regenoffantei = _ro ; sw_anteimotor = _am ; }

  void setvar ( double p , double v , car_stat s , double td ,
                double ta , double pt ) {		// 変数初期値セット
    pos = p ; vel = v ; stat = s ;
    tdept = td ; taudx = ta ; ptime = pt ; }
  void distvar ( FILE * td ) {		// 変数初期値セーブ
    fprintf ( td , "setvar %.12e %.12e %i %.12e %.12e %.5f\n" ,
              pos , vel , stat , tdept , taudx , ptime ) ; }
  void setcccl ( double a , double b )			// cc , cl のセット
  { ccv = a ; clv = b ; }				// 引数 cc , cl
  void setcscomm ( cs_command c ) { ccmd = c ; }	// ccmd セット

  void setcarno ( int t ) { carno = t ; }	// 車両番号のセット
  int car_number () const { return carno ; }
  int cs_number () const { return csno ; }

  string const & getTrainTypeKey () const { return * train_type_key ; }

  void setssimps ( double a , int b )	// 車両の起点側の変電所まで
  { ssno = b ; sis = a ; }		// のインピーダンスをセット
  void setssimpe ( double a , int b )	// 車両の終点側の変電所まで
  { seno = b ; sie = a ; }		// のインピーダンスをセット
  void setnosss () { nosss = true ; }	// 起点側変電所なし をセット
  void setnosse () { nosse = true ; }	// 終点側変電所なし をセット
  void resetnos () {			// 起終点側変電所とも
    nosss = nosse = false ; }			// ありとする
  void distnxx ( FILE * td )		// nxx のセット
  { fprintf ( td , "setnxx %i %i\n" , nxx -> dptnum () , nxx -> dpttbl () ) ; }

  // nxx のセット
  void setNextstaPointer ( nextsta const * ) ;
  void setNextstaPointer_for_disttrain ( nextsta const * ) ;
			// ( for disttrain )

  // 電圧だけセット. 2007. 10. 1. Moved to trteta.cc , no longer inline
  void teta_v_only () ;

  // 媒介変数の最大値
  double getMaximumTeta () ;
  double getMaximumTeta ( double ) ;

  // 媒介変数の最小値
  double getMinimumTeta () ;
  double getMinimumTeta ( double ) ;

  // 電圧から媒介変数を求める
  double getTetaFromVoltage () ;
  double getTetaFromVoltage ( double ) ;

  void setviold () ;
  void restorevi () ;
  void setpbdata ( powerdata , brakedata , autodata ) ;
        	// teta_vi , notchrate 関数のためのデータのセット

  void stnobj_init () ;		// station_obj に通信をかける（初期化時）
  void stnobj_comm () ;		// station_obj に通信をかける（それ以外）

  void tell_signal_change () const {	// 信号現示変化を通信
    ( ( train * ) this ) -> signal_changed = true ;
  }

  void push_to_station_init ( to_station ) ;	// を station_obj に
  void push_from_station_init ( from_station ) ;
			// from_station オブジェクトを station_obj に

private :
  void membercopy ( const train & x ) ;	// 基本クラス private member copy

} ;


// teta から電圧を, また電圧から teta を, 求める
double calculateVoltageFromCarTeta ( double ) ;
double calculateCarTetaFromVoltage ( double ) ;


#endif /* ! ___TRAIN_HH */
