// 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.)
// disttrn.cc --- class feeder functions: disttrain
// $Id: disttrn.cc,v 2.4 1994/12/27 11:47:32 rt Exp $


#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <vector>

#include "kidenrt.hh"

//#define DEBUG

using std :: cerr ;
using std :: endl ;
using std :: vector ;


// 列車状態の初期化
void
feeder :: disttr_trinit
()
{
  int cz = 0 ;		// すでに初期化終了した列車たち
  for ( int i = 0 ; i < ndp ; ++ i )
  {
    for ( int j = cz ; j < cz + getDPT ( i ) . car_number () ; ++ j )
    {
      getCAR ( j ) . setvar
	( getDPT ( i ) . initpos () , getDPT ( i ) . initvel () ,
	  getDPT ( i ) . carstat () , getDPT ( i ) . departuretime () ,
	  getDPT ( i ) . delaytime () , 0.0 ) ;
      getCAR ( j ) . setNextstaPointer_for_disttrain
        ( getDPT ( i ) . initnxx () ) ;
      getCAR ( j ) . setstatold ( Stn_stop ) ;
    }
    cz += getDPT ( i ) . car_number () ;	// この数の列車はもう終了
  }
}    

/*********************************************************************
 TODO: 列車初期配置を求める問題。 1994. Oct. 21. --- RT

 列車初期配置は列車と列車の間隔が問題になる場合には非常に決めにくい。
 どのようにこれを与えるか？  少なくとも初期配置の段階ではこのような
 問題が起きない範囲内の配置のみを許すか？  初期配置の段階での問題は
 シミュレーション開始後無視するプログラムにするか？  初期配置の段階
 で問題が起き、それを修正できないのは、列車が近づき過ぎていることが
 わかったときにすでに駅停車のためのブレーキをかけはじめている場合。
 これ以外は（基本的には）すべてOKのはず。ただし、disttrain の最中と
 それ以外とで信号制約の取り扱いを変更する必要があるが、これは面倒か
 どうか。もう一つは初期配置の段階でそれを考慮するようにする方法。こ
 れはかなり面倒。

 列車配置について、列車性能は分けて入れるにしてもダイヤパターンに1
 つの列車性能データがあればよい。ダイヤパターン内を複数の列車性能で
 シミュレートする必然性は薄い。そうなれば、列車の性能は一個のダイヤ
 パターン内にいる列車については同一であることが保証されるから、ダイ
 ヤパターンごとに列車オブジェクトをコピーできる！  列車オブジェクト
 のコピーをしっかり設計・製作する必要がある。

*********************************************************************/

// 列車の初期位置を求める
void
feeder :: disttrain
()
{
  l_ofs << "Disttrain start" << endl ;

  // 初期位置既決定列車数
  vector < int > tt ;

  // 各列車パターン毎にゼロ
  for ( int i = 0 ; i < ndp ; ++ i )
    tt . push_back ( 0 ) ;

  // Initializing time
  t_sim = 0.0 ;

  // 車両の状態の初期化
  disttr_trinit () ;
  int cz ;
  bool sw_initial_data_not_printed = true ;
  while ( 1 )
  {
    cz = 0 ;

    // 次位置計算（電圧一定）
    for ( int i = 0 ; i < ndp ; ++ i )
    {
      // 列車の初期位置への到達を検知
      if ( tt [ i ] < getDPT ( i ) . car_number ()
           && t_sim >= getDPT ( i ) . wholetime ()
           * tt [ i ] / getDPT ( i ) . car_number ()
           + getDPT ( i ) . phasevalue () )
      {
        cerr << "Reached: car " << cz + tt [ i ]
             << " pos: " << getCAR ( cz + tt [ i ] ) . position ()
             << " vel: " << getCAR ( cz + tt [ i ] ) . velocity ()
             << " time: " << t_sim << endl ;
        l_ofs << "Reached: car " << cz + tt [ i ]
              << " pos: " << getCAR ( cz + tt [ i ] ) . position ()
              << " vel: " << getCAR ( cz + tt [ i ] ) . velocity ()
              << " time: " << t_sim << endl ;
        getCAR ( cz + tt [ i ] ) . zlenrun () ;
        getCAR ( cz + tt [ i ] ) . setstpos () ;
        getCAR ( cz + tt [ i ] ) . resettd ( t_sim ) ;
        ++ ( tt [ i ] ) ;
      }
      // 列車を動かす  
      for ( int j = cz + tt [ i ] ;
            j < cz + getDPT ( i ) . car_number () ; ++ j )
      {
#ifdef DEBUG
        cerr << "Searching: car " << j << " pos: "
             << getCAR ( j ) . position () << " vel: "
             << getCAR ( j ) . velocity () << " time: " << t_sim << endl ;
        l_ofs << "Searching: car " << j << " pos: "
              << getCAR ( j ) . position () << " vel: "
              << getCAR ( j ) . velocity () << " time: " << t_sim << endl ;
#endif
        // Get the notch rate
        getCAR ( j ) . notchrate () ;
#ifdef DEBUG
        l_ofs << "Notchrate ended" << endl ;
#endif
        // 電圧を定める
        getCAR ( j ) . teta_vi () ;
#ifdef DEBUG
        l_ofs << "Theta-vi ended" << endl ;
#endif
        runtrsub ( j ) ;
#ifdef DEBUG
        cerr << "dpt: " << i ;
        cerr << ", car: " << j << " calculation ended" << endl ;
#endif
      }
      cz += getDPT ( i ) . car_number () ;
    }

    // 終了判定
    int swend = 1 ;
    for ( int i = 0 ; i < ndp ; ++ i )
    {
      swend = swend && ( tt [ i ] == getDPT ( i ) . car_number () ) ;
    }
    if ( swend ) break ;

    // 終了していなければ increment t_sim
    t_sim += deltah ;
    sw_initial_data_not_printed = false ;
  }

  if ( g_sw_station_object_valid )
  {
    for ( int i = 0 ; i < ncar; ++ i )
    {
      // station_obj に通信をかける
      getCAR ( i ) . stnobj_init () ;
    }
    for ( int i = 0 ; i < stnobj . number () ; ++ i )
    {
      stnobj [ i ] -> headway_cal_init () ;
    }
  }
  g_sw_disttrain_ended = true ;
  l_ofs << "Disttrain ended" << endl ;
}
