// 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.)
// stnobj_s.cc --- functions for class station_obj_stationstop_variation
// $Id: stnobj_s.cc,v 2.4 1994/12/27 11:49:38 rt Exp $

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

#include "stnobj_s.hh"
#include "train.hh"

//#define DEBUG

// constructor
station_obj_stationstop_variation::station_obj_stationstop_variation
() : station_obj() {
    d_init = 0.0;
    sw_disturb = false;
    sw_disturbance_done = false;
    sw_disturb_control = false;
    sw_delay_comm_yet = false;
    tsim_distcomm = 0.0;
    cd_type = Without_control;
    control_station_object_number = -1;
    control_station_object_value = 0.0;
    control_station_object_time = 0.0;
    tarr_delay_add = 0.0;
    tdept_delay_add = 0.0;
    tdept_delay_add_imove = 0;
}

// constructor: X(X&)
station_obj_stationstop_variation::station_obj_stationstop_variation
( const station_obj_stationstop_variation& x )
: station_obj( x ) {
    membercopy( x );
}

// 代入・初期化用
void station_obj_stationstop_variation::membercopy
( const station_obj_stationstop_variation& x ) {
    station_obj::membercopy( x );
    d_init = x.d_init;
    sw_disturb = x.sw_disturb;
    sw_disturbance_done = x.sw_disturbance_done;
    sw_delay_comm_yet = x.sw_delay_comm_yet;
    sw_disturb_control = x.sw_disturb_control;
    tsim_distcomm = x.tsim_distcomm;
    cd_type = x.cd_type;
    control_station_object_number = x.control_station_object_number;
    control_station_object_value = x.control_station_object_value;
    control_station_object_time = x.control_station_object_time;
    tarr_delay_add = x.tarr_delay_add;
    tdept_delay_add = x.tdept_delay_add;
    tdept_delay_add_imove = x.tdept_delay_add_imove;
}

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

// 列車出発告知
void
station_obj_stationstop_variation::this_train_will_depart
( const train* trptr_arg ) const {
    // 前半
    this_train_will_depart_aaa( trptr_arg );

    station_obj_stationstop_variation* stox
        = ( station_obj_stationstop_variation* ) this;	// const外しの cast

    // tdept_delay_add をゼロリセット
    stox->tdept_delay_add = 0.0;	// なぜこうするのだろう？
    
    // 後半    
    this_train_will_depart_baa( trptr_arg );
}

// 駅到着時分の遅延をリセット ＋ 駅停車時分のフラクチュエーション
// 停車時分フラクチュエーションには高木方式を導入
//
// $t_d$ : 発車時刻（求めるもの） (tdept)
// $t_{do}$ : 前列車の発車時刻 (tdept_prev)
// $t_a$ : 到着時刻 (tarrive = temp_fs.tarrive)
// $t_h$ : 時隔 (glob_head)
// $t_S$: 停車時分 (tstop = operator[]( imove ).tstop)
// $t_{SV}$: 停車時分のうち乗降人員に比例しない分 (glob_t_sv)
//
// t_d = \dfrac{t_h * (t_a + t_{SV}) - t_{do} * (t_S - t_{SV})}
//             {t_h - t_S + t_{SV}}
//
void
station_obj_stationstop_variation::stationstop_variation_func
( from_station& temp_fs, int imove ) {

    // tarr_delay_add をリセット
    tarr_delay_add = 0.0;

    // 一つ前の列車の出発時刻
    double tdept_prev
        = train_departure[ temp_fs.voie ].tdept
        + train_departure[ temp_fs.voie ].tdept_delay;

    // この列車の到着時刻
    double tarrive = temp_fs.tarrive;

    // この列車の停車時分
    // operator[]( imove ).tstop にはノミナル停車時分が入っているとする
    double tstop = operator[]( imove ).tstop;

    // まずは期待される出発時刻計算
    double tdept = glob_head * ( tarrive + glob_t_sv );
    tdept -= tdept_prev * ( tstop - glob_t_sv );
    tdept /= glob_head - tstop + glob_t_sv;

    // 希望出発時刻に対し遅れを算出
    temp_fs.tdept_delay = tdept - temp_fs.tdept;

    // 遅れ時分がマイナスの場合の処理
    // 現在列車が持っている遅れ: operator[]( imove ).taudx
    // temp_fs.tdept_delay < - operator[]( imove ).taudx ならば
    // tdept_delay をその値まで戻す
    double x_vh = - operator[]( imove ).taudx;
    if ( temp_fs.tdept_delay < x_vh ) {
        temp_fs.tdept_delay = x_vh;
    }

    // 駅停車時分乱れ関係の指示
    stationstop_variation_func_delay( temp_fs, imove );
}

// train_departure[ * ].tdept_delay を探してきて返す
double
station_obj_stationstop_variation::tdept_delay
( const train* trptr_arg ) const {
    station_obj_stationstop_variation* stox
        = ( station_obj_stationstop_variation* ) this;	// const外しの cast
    int imove = stox->which_in_train_departure( trptr_arg );
    double ret_val = stox->train_departure[ imove ].tdept_delay;
    if ( imove == tdept_delay_add_imove ) {
        ret_val += tdept_delay_add;
    }
    return ret_val;
}

// operator[]( * ).tarr_delay を探してきて返す
double
station_obj_stationstop_variation::tarr_delay
( const train* trptr_arg ) const {
    station_obj_stationstop_variation* stox
        = ( station_obj_stationstop_variation* ) this;	// const外しの cast
    int imove = stox->which_in_to_station( trptr_arg );
    double ret_val = stox->operator[]( imove ).tarr_delay;
    return ret_val + tarr_delay_add;
}

// 駅停車時分乱れ関係の指示（親玉）
// station_obj::from_station_generate() 関数（到着処理）
// から呼ばれる
// 停車時分乱れを起こすケースを pickup
void
station_obj_stationstop_variation::stationstop_variation_func_delay
( from_station& temp_fs, int imove ) {

    // 遅れ発生処理をそもそも行わないケース
    if ( ! sw_disturb ) {
        tdept_delay_add = 0.0;
        return;
    }

    // まだ行わないケース
    if ( g_sw_freerun_cycle || ( ! g_sw_disttrain_ended ) ) {
        tdept_delay_add = 0.0;
        return;
    }

    // すでに遅れ発生処理を行ったケース
    if ( sw_disturbance_done ) {
        if ( sw_delay_comm_yet ) {
            stationstop_variation_delay_comm();	// 制御先への通信処理
        }
        tdept_delay_add = 0.0;
        return;
    }

    // 遅れ発生処理を行う
    stationstop_variation_func_delay_core( temp_fs, imove );
}


// 駅停車時分乱れ関係の指示（親玉）
// 遅れ発生処理をほんとうに行うルーチン
void
station_obj_stationstop_variation::stationstop_variation_func_delay_core
( from_station& temp_fs, int imove ) {

    // これだけ遅れる
    tdept_delay_add = d_init;
}

// 列車群制御のための通信を処理
void
station_obj_stationstop_variation::stationstop_variation_delay_comm
() {

    switch ( cd_type ) {

      case Without_control:	// なにもしない
        sw_delay_comm_yet = false;
        return;
        break;

      case Stop_at_station:	// 駅停車抑止
        // ほんとうはここに
        // 駅停車抑止量を通信する部分を書き込むはずだった
        sw_delay_comm_yet = false; // 無条件に false にするのはいけない
        return;
        break;

      case Slow_down_between:	// 駅間走行時分延伸
        // ほんとうはここに
        // 駅間走行時分延伸量を通信する部分を書き込むはずだった
        sw_delay_comm_yet = false; // 無条件に false にするのはいけない
        return;
        break;

    }
}
