// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// trn_stno.cc --- class train functions on nextmotion: nm_stnobj
// -----
// ChangeLog:
// 2007. 11. 22
//  Redirected log messages to l_file.
// -----

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

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

#define INVLIM 1e-5

//#define TIMEPRINT
//#define PRATEBUG

//#define DEBUG



// 次位置演算: station_obj からの通信によって変更処理
// *** 力行・惰行・定速走行時早着を検知→ブレーキ
bool
train :: nm_stnobj_brake
()
{
  if ( g_sw_station_object_valid && g_sw_disttrain_ended )
  {
    // 信号系有効時のみチェック

    double ontx = ontimesub ( pos , pgrad , vel , t_sim ) ;

    double 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 - deltah * 2.0 )
    {
      // 列車は定時より早着 -> ブレーキへ
      stat = Brake ;
      brakev = - 1.0 ;	// 負の目標速度：ontime Brake 条件
      rnotchold = rnotch = - 1.0 ;
      iamcoast = true ;			// 惰行領域を設定
      iamconst = false ;
      return true ;
    }
  }
  return false ;
}



// 次位置演算: station_obj からの通信によって変更処理
// *** 惰行・定速走行・ブレーキ時遅着を検知→加速
bool
train :: nm_stnobj_power
()
{
  if ( g_sw_station_object_valid && g_sw_disttrain_ended )
  {
    // 信号系有効時のみチェック

    double ontx = ontimesub ( pos , pgrad , vel , t_sim ) ;

    double 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 + deltah * 2.0 )
    {
      // 列車が遅れている -> 再力行へ
#ifdef DEBUG
      cerr << StrPrintf
        ( "ontx, tarrive = %.2f %.2f" , ontx - tdept + taudx ,
          nxx -> tarrive ( pfirst ) + x_tard ) << endl << "regen" << endl ;
#endif
      // pfirst はこのルーチンではいじらない
      iamconst = true ;
      iamcoast = false ;	// 力行領域を設定
      cpsw = false ;		// cpsw リセット
      if ( vel >= nxx -> vlimit ( pgrad ) && nxx -> vlimit ( pgrad ) >= INVLIM
           && tresist ( vel , pgrad ) < 0 )
      {
        
        train_ParamFunc *__pf = getNewParamFuncCalculator () ;
        __pf -> prepareMaximumEffort () ;
        double tfp = __pf -> getMaxTractiveEffort () ;
        delete __pf ;
        // ----
        // 2010. 1. 19 NOTE --- tracf(vel,v,-1) returns maximum regenerative
        // effort. tracf(vel,v,-1)>=tresist(vel,pgrad) would mean that (1)
        // both regenerative effort and the train resistance (sum of running
        // resistance and gradient resistance) are negative, and
        // (2) fabs(tracf(vel,v,-1))<=fabs(tresist(vel,pgrad)), i.e. the
        // train cannot maintain speed at the down gradient. Probably tracf
        // (vel,v,-1) is a bug and should be tracf(vel,v,1). Hence use tfp.
        // ----
//         if ( tracf ( vel , v , -1.0 ) >= tresist ( vel , pgrad ) )
        if ( tfp >= tresist ( vel , pgrad ) )
        {
          // 牽引力が定速走行を維持できるだけある
          stat = Const_vel ;
        }
        else
        {
          // 牽引力が定速走行を維持できるほど確保できない
          stat = Power ;
          rnotchold = rnotch = 1.0 ;
        }
      }
      else
      {
        stat = Power ;			// 力行状態へ転向
        rnotchold = rnotch = 1.0 ;
      }
      return true ;
    }
  }
  return false ;
}
