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

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

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

//#define DEBUG

// constructor
station_obj::station_obj
() : NoRefTable<to_station> () {
    first_headcal_ended = false;
    stnno = niolno = nvoie = 0;
    stnobjtype = Doubletrack_no_cross;
}

// 代入・初期化用
void station_obj::membercopy
( const station_obj& x ) {
    nvoie = x.nvoie;
    stnobjtype= x.stnobjtype;
    depart_arrival = x.depart_arrival;
    arrival_depart = x.arrival_depart;
    arrival_arrival = x.arrival_arrival;
    depart_depart = x.depart_depart;
}

// 代入演算子の overload
station_obj& station_obj::operator=
( const station_obj& x ) {
    if (&x == this) return *this;
    NoRefTable<to_station>::operator=( x );
    membercopy( x );
    return *this;
}

// to_station オブジェクトを削除
void station_obj::remove
( int nrm ) {
    if ( nrm < 0 || nrm >= num ) {
        error26_name();		// エラーメッセージ
        exit( 26 );
    }
    while ( ++nrm < num ) {
        data[ nrm - 1 ] = operator[]( nrm );
    }
    num--;
    return;
}

// train_departure の配列の中にポインタを見つけさせる
int station_obj::which_in_train_departure
( const train* trptr_arg ) const {
    int imove = 0;
    int sw_nomove = -1;
    station_obj* stox = ( station_obj* ) this;	// const外しの cast
    while ( imove < nvoie ) {
        if ( trptr_arg != stox->train_departure[ imove ].tr_ptr ) {
            imove++;
        } else {
            sw_nomove = 0;
            break;
        }
    }
    if ( sw_nomove ) {
      l_ofs << "Error: no train like this seems to be departing." << endl
            << StrPrintf ( "Error:  Car No. %d, CS No. %d" ,
                           trptr_arg -> car_number () ,
                           trptr_arg -> cs_number () ) << endl
            << StrPrintf
        ( "Error:  Stnobj No. %d, train_departure[0].tarrive %10.4f" ,
          get_stnno () , stox -> train_departure [ 0 ] . tarrive ) << endl ;
      cerr << "Error: no train like this seems to be departing." << endl
           << StrPrintf ( "Error:  Car No. %d, CS No. %d" ,
                          trptr_arg -> car_number () ,
                          trptr_arg -> cs_number () ) << endl
           << StrPrintf
        ( "Error:  Stnobj No. %d, train_departure[0].tarrive %10.4f" ,
          get_stnno () , stox -> train_departure [ 0 ] . tarrive ) << endl ;
      exit ( 61 ) ;
    }
    return imove ;
}



// to_station 配列の中にポインタを見つけさせる
int
station_obj :: which_in_to_station
( train const * trptr_arg )
  const
{
  int imove = 0 ;
  int sw_nomove = - 1 ;
  while ( imove < number () )
  {
    if ( trptr_arg != operator[] ( imove ) . tr_ptr )
    {
      ++ imove ;
    }
    else
    {
      sw_nomove = 0 ;
      break ;
    }
  }
  if ( sw_nomove )
  {
    l_ofs << "Error: station_obj does not contain this train" << endl
          << StrPrintf ( "Error:   Car No. %d, CS No. %d" ,
                         trptr_arg -> car_number () ,
                         trptr_arg -> cs_number () ) << endl
          << StrPrintf
      ( "Error:   Stnobj No. %d, to_station: %d, tarrive %10.4f" ,
        get_stnno () , number () , data [ 0 ] . tarrive ) << endl ;
    cerr << "Error: station_obj does not contain this train" << endl
         << StrPrintf ( "Error:   Car No. %d, CS No. %d" ,
                        trptr_arg -> car_number () ,
                        trptr_arg -> cs_number () ) << endl
         << StrPrintf
      ( "Error:   Stnobj No. %d, to_station: %d, tarrive %10.4f" ,
        get_stnno () , number () , data [ 0 ] . tarrive ) << endl ;
    exit ( 60 ) ;
  }
  return imove ;
}

// train_departure[ * ].do_not_depart を探してきて返す
bool station_obj::do_not_depart
( const train* trptr_arg ) const {
    station_obj* stox = ( station_obj* ) this;	// const外しの cast
    int nwhich = stox->which_in_train_departure( trptr_arg );
#ifdef DEBUG
    cerr << "departing voie: " << nwhich << "\n";
#endif
    return stox->train_departure[ nwhich ].do_not_depart;
}

// train_departure[ * ].tdept_delay を探してきて返す
double station_obj::tdept_delay
( const train* trptr_arg ) const {
    station_obj* stox = ( station_obj* ) this;	// const外しの cast
    return stox->train_departure
        [ stox->which_in_train_departure( trptr_arg ) ].tdept_delay;
}



// operator[]( * ).tarr_delay を探してきて返す
double
station_obj :: tarr_delay
( train const * trptr_arg )
  const
{
  return operator[] ( which_in_to_station ( trptr_arg ) ) . tarr_delay ;
}



// to_station 配列中の列車が到着すべき番線が使用中なら
// true を返す関数
bool station_obj::voie_occupied
( const train* trptr_arg ) const {
    station_obj* stox = ( station_obj* ) this;	// const外しの cast
    int nx_tostn = stox->which_in_to_station( trptr_arg );
    if ( nx_tostn != 0 ) {
        // to_station 配列に前がいれば不許可!
        return true;
    }
    return stox->train_departure
        [ ( *stox )[ nx_tostn ].voie ].is_at_station;
}
