// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// trn_regn.cc --- class train functions on nextmotion: nm_regen
// -----
// ChangeLog:
// 2010. 1. 19
//  Removed use of member function train::tracf().
// 2007. 11. 22
//  Redirected log messages to l_file.
// -----

#include <cstdio>
#include <cstdlib>
#include <cmath>

#include "train.hh"
#include "StrPrintf.hh"

#define INVLIM 1e-5

//#define DEBUG
//#define TIMEPRINT


// 回生のみ中の次位置演算
void
train :: nm_regen
( double tracff )
{
  // ----
  // NOTE: 2010. 1. 20 -- emrn no longer used.
  // ----
  // tracff *= emrn ;	// added 04 Jun 92
  //                    // 発振防止アルゴリズムのため

#ifdef DEBUG
  cerr << StrPrintf ( "nm_regen, tracff = %.1f" , tracff ) << endl ;
#endif
  iamcoast = iamconst = false ;
  enableMechanicalPowerCalculation () ;
  npos ( tracff ) ;
  disableMechanicalPowerCalculation () ;
  if ( bklen () * direc () >= nxx -> parrive () * direc () )
  {
    stat = Brake ;
    brakev = nxx -> varrive () ;
    iamconst = false ;
    iamcoast = true ;
    rnotchold = rnotch = - 1.0 ;
    ++ pfirst ;
    return ;			// off-brake 条件
  }

  if ( vlimitbrake () )
  {
    // 前方制限速度による減速→惰行へ(要・再検討)
    cpsw = true ;
    iamconst = false ;
    iamcoast = true ;
    return ;
  }

  double ontx = ontimesub ( pos , pgrad , vel , t_sim ) ;
  double x_tard = 0.0 ;	// 到着遅れ時分の期待値
  if ( g_sw_station_object_valid && g_sw_disttrain_ended )
  {
    // 信号系有効時のみチェック
    // **** nxx -> tarr_delay ( this ) : 信号系無効時は zero なのだが
    x_tard = nxx -> tarr_delay ( this ) ;	// これが通常の話
    if ( g_sw_stop_between_oriented && sw_x_btws )
    {
      // 駅間停止指向で駅間停止位置を過ぎていない場合
      x_tard = 0.0 ;	// 遅れなしとしてパターンを生成
    }
  }

  if ( ontx - tdept + taudx >= nxx -> tarrive ( pfirst ) + x_tard )
  {
#ifdef DEBUG
    cerr << StrPrintf ( "ontx, tarrive = %.2f %.2f" ,
                        ontx - tdept + taudx ,
                        nxx -> tarrive ( pfirst ) + x_tard ) << endl
         << "regen" << endl ;
#endif
    ++ pfirst ;
    iamconst = false ;
    iamcoast = true ;
    if ( tresist ( vel , pgrad ) > 0 || vel < nxx -> vlimit ( pgrad )
         || nxx -> vlimit ( pgrad ) < INVLIM )
    {
      // ontime 運転条件
      stat = Coast ;
      rnotchold = rnotch = 0.0 ;
    }
    else
    {
      stat = Const_vel;
    }
    return ;
  }

  train_ParamFunc *__pf = getNewParamFuncCalculator () ;
  __pf -> prepareMaximumEffort () ;
  double tfb = __pf -> getMaxBrakingEffort () ;
  delete __pf ;
  if ( vel > nxx -> vlimit ( pgrad ) && nxx -> vlimit ( pgrad ) >= INVLIM
       && tfb > tresist ( vel , pgrad ) )
  {
    // ここも怪しいぞ
    stat = Const_vel ;
    iamcoast = false ;
    iamconst = true ;
  }
}
