// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// rf_ffile.cc --- read data from files: F file
// -----
// ChangeLog:
// 2007. 11. 21
//  Redirected log messages to l_file.
// -----

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>

#include "kidenrt.hh"
#include "StrPrintf.hh"

//#define DEBUG

// feeder.dat を読むファイル
void
feeder :: rf_ffile
()
{
  FILE * feeddat = fopen ( f_file , "r" ) ;
  if ( ! feeddat ) err_access ( f_file ) ;
  int sia ;
  double sda ;
  while ( 1 )
  {
    getcommand ( feeddat , f_file ) ;
    if ( cmpcommand ( "feeders" ) )
    {
      // while 文を抜ける
      break ;
    }
    else if ( cmpcommand ( "nominal_voltage" ) )
    {
      getdouble ( feeddat , f_file , nominal_volt ) ;
      l_ofs << StrPrintf ( "nominal voltage = %.1f " , nominal_volt ) ;
      l_ofs << endl ;
    }
    else if ( cmpcommand ( "options" ) )
    {
      getcommand ( feeddat , f_file ) ;
      if ( cmpcommand ( "ccalresult" ) )
      {
	if ( g_sw_ccalresult )
	{
	  g_sw_ccalresult = false ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_ccalresult to false" )
                << endl ;
	}
	else
	{
	  g_sw_ccalresult = true ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_ccalresult to true" )
                << endl ;
	}
      }
      else if ( cmpcommand( "ssdirection" ) )
      {
	if ( g_sw_ss_direction )
	{
	  g_sw_ss_direction = false ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_ss_direction to false" )
                << endl ;
	}
	else
	{
	  g_sw_ss_direction = true ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_ss_direction to true" )
                << endl ;
	}
      }
      else if ( cmpcommand ( "kilowatt_subout" ) )
      {
	if ( g_sw_kilowatt_subout )
	{
	  g_sw_kilowatt_subout = false ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_kilowatt_subout to false" )
                << endl ;
	}
	else
	{
	  g_sw_kilowatt_subout = true ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_kilowatt_subout to true" )
                << endl ;
	}
      }
      else if ( cmpcommand ( "per_car_out" ) )
      {
	if ( g_sw_per_car_out )
	{
	  g_sw_per_car_out = false ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_per_car_out to false" )
                << endl ;
	}
	else
	{
	  g_sw_per_car_out = true ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_per_car_out to true" )
                << endl ;
	}
      }
      else if ( cmpcommand ( "nosetviold" ) )
      {
	if ( g_sw_nosetviold )
	{
	  g_sw_nosetviold = false ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_nosetviold to false" )
                << endl ;
	}
	else
	{
	  g_sw_nosetviold = true ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_nosetviold to true" )
                << endl ;
	}
      }
      else if ( cmpcommand ( "csv_has_noshibo" ) )
      {
	if ( g_sw_csv_has_noshibo )
	{
	  g_sw_csv_has_noshibo = false ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_csv_has_noshibo to false" )
                << endl ;
	}
	else
	{
	  g_sw_csv_has_noshibo = true ;
	  l_ofs << StrPrintf ( "OK, toggled g_sw_csv_has_noshibo to true" )
                << endl ;
	}
      }
      else if ( cmpcommand ( "csv_has_rnotch_for_capper" ) )
      {
	if ( g_sw_csv_has_rnotch_for_capper )
	{
	  g_sw_csv_has_rnotch_for_capper = false ;
	  l_ofs << "OK, toggled g_sw_csv_has_rnotch_for_capper to false"
                << endl ;
	}
	else
	{
	  g_sw_csv_has_rnotch_for_capper = true ;
	  l_ofs << "OK, toggled g_sw_csv_has_rnotch_for_capper to true"
                << endl ;
	}
      }
      else if ( cmpcommand ( "csv_without_quotation" ) )
      {
	if ( g_sw_csv_without_quotation )
	{
	  g_sw_csv_without_quotation = false ;
	  l_ofs << "OK, toggled g_sw_csv_without_quotation to false"
                << endl ;
	}
	else
	{
	  g_sw_csv_without_quotation = true ;
	  l_ofs << "OK, toggled g_sw_csv_without_quotation to true"
                << endl ;
	}
      }
      else err_eof ( f_file ) ;
    }
    else err_eof ( f_file ) ;
  }
  getint ( feeddat , f_file , feeders ) ;
  l_ofs << StrPrintf ( "feeder setvar = %i " , feeders ) ;

  // dp_command の読み込み
  getcommand ( feeddat , f_file ) ;

  // 初期化 : -Wall warning 回避のため
  dp_command dpcmx = No_comm ;
  if ( cmpcommand ( "Delay_yes" ) )
    dpcmx = Delay_yes ;
  else if ( cmpcommand ( "Buffer_yes" ) )
    dpcmx = Buffer_yes ;
  else if ( ! ( cmpcommand ( "No_comm" ) ) )
    err_eof ( f_file ) ;
  l_ofs << tmpch << endl ;

  // dp_command のセット
  for ( int i = 0 ; i < ndp; ++ i )
    getDPT ( i ) . setdc ( dpcmx ) ;

  // feedline 配列の確保
  for ( int i = 0 ; i < feeders ; ++ i )
  {
    feedline * x = new feedline ;
    if ( ! x )
    {
      std :: cerr << "Error: memory allocation fault" << std :: endl ;
      exit ( 37 ) ;
    }
    vec_fln . push_back ( x ) ;

    // *** feedline object に饋電線番号を伝達
    getFLN ( i ) . setnfline ( i ) ;
    getFLN ( i ) . renewssc ( nss + ncar ) ;
  }
  getcommand ( feeddat , f_file ) ;
  cmpcommand ( "freeruns" , f_file ) ;
  getint ( feeddat , f_file , nfree ) ;
  l_ofs << StrPrintf ( "free running cycle(s) = %i" , nfree ) << endl ;
  getcommand ( feeddat , f_file ) ;
  cmpcommand ( "simulatings" , f_file ) ;
  getint ( feeddat , f_file , nsim ) ;
  l_ofs << StrPrintf ( "simulating cycle(s) = %i" , nsim ) << endl ;

  // 饋電線の形状、饋電定数、長さ
  double sdb ;

  // 初期化: -Wall warning 回避のため
  feeder_shape fsp = Long ;

  for ( int i = 0 ; i < feeders ; ++ i )
  {
    getcommand ( feeddat , f_file ) ;
    if ( strcmp ( tmpch , "setfeedline" ) != 0 )
      err_eof ( f_file ) ;
    if ( gettwodbls ( feeddat , sda , sdb ) == EOF )
      err_eof ( f_file ) ;
    getcommand ( feeddat , f_file ) ;
    static char tcx [ TMPCHSIZ ] ;
    strcpy ( tcx , tmpch ) ;
    if ( strcmp ( tmpch , "Long" ) == 0 )
      fsp = Long ;
    else if ( strcmp ( tmpch , "0" ) == 0 )
    {
      fsp = Long ;
      strcpy ( tcx , "Long" ) ;
    }
    else if ( strcmp ( tmpch , "Circle" ) == 0 )
      fsp = Circle ;
    else if ( strcmp ( tmpch , "1" ) == 0 )
    {
      fsp = Circle ;
      strcpy ( tcx , "Circle" ) ;
    }
    else err_eof ( f_file ) ;
    l_ofs << StrPrintf ( "feedline ( %i ) set variables: %.3f %.5f %s" ,
                         i , sda , sdb , tcx ) << endl ;
    getFLN ( i ) . setvar ( sda , sdb , fsp ) ;
  }

  // 変電所接続点データ→ feedline, elecchar (sub)
  getcommand ( feeddat , f_file ) ;
  if ( strcmp ( tmpch , "ssfeederconnections" ) != 0 ) err_eof ( f_file ) ;
  if ( getint ( feeddat , sia ) == EOF ) err_eof ( f_file ) ;
  l_ofs << StrPrintf ( "number of substation/feeder connection data = %i" ,
                       sia ) << endl ;
  feedpos fp ;
  ssfeedconnect sfcn ;
  for ( int i = 0 ; i < sia ; ++ i )
  {
    gettwoints ( feeddat , f_file , fp . nfline , fp . csno ) ;
    getthreedbls ( feeddat , f_file , fp . pos , fp . sttimp , fp . endimp ) ;
    if ( fp.nfline < 0 || fp.nfline >= feeders
	 || fp.csno < 0 || fp.csno >= nss )
      err_eof ( f_file ) ;
    l_ofs << StrPrintf ( "feedline( %i ) *= %i %.4f %.5f %.5f" ,
                         fp . nfline , fp . csno , fp . pos , fp . sttimp ,
                         fp . endimp ) << endl ;
    getFLN ( fp . nfline ) *= fp ;
    sfcn = fp ;

    // Change 2007. 10. 10 by RT. For various reasons, the connection between
    // a "feeder" and a substation must be at one point only. The following
    // routine checks duplicate connections and aborts if found.
    // 饋電線と変電所の接続点は1カ所のみ。それを検査し，みつかったら停止。
//     for ( int i = 0 ; i < getSUB ( fp . csno ) . feedcon () . number () ;
//           ++ i )
//     {
//       if ( getSUB ( fp . csno ) . feedcon () [ i ] . nfline == fp . nfline )
//         err_eof ( f_file ) ;
//     }

    // Error not found. Add the connection data into substation.
    // エラー見つからず。直接たたき込む
    getSUB ( fp . csno ) . feedcon () += sfcn ;
  }
  fclose ( feeddat ) ;

  // 行列の大きさ初期化
  ymtx . renewmn ( ncss , ncss ) ;
  gff_xx . renewmn ( ncss , ncss ) ;
  gamma . renewmn ( ncss ) ;
  fvec . renewmn ( ncss ) ;

  // 簡単なデータチェック
  bool patc = false ;
  for ( int i = 1 ; i < ndp ; ++ i )
  {
    if ( getDPT ( i ) . ptntime () != getDPT ( i - 1 ) . ptntime () )
      patc = true ;
  }
  if ( patc ) err_eof ( f_file ) ;
  t_cyc = getDPT ( 0 ) . ptntime () ;
}
