// 「江バ電事故」による人身事故シミュレータ

/*
  gcc -g train.cpp -o train
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // usleep()

/* 
   ■「江バ電」のザックリとした仕様

   (1)まず「江バ電」ですが、これは私が毎日お世話になっている小田急電鉄の
   小田原線をイメージして、スペックを決めました。

   (2)といっても、相互乗り入れ、他の路線との連携(多摩線、片瀬江ノ島線等)の
   ことは、全部忘れました。計算が面倒だったからです。

   (3)さらに言えば、駅を作るのも止めました。人身事故の発生には駅は関係が
   ないと考えたからです。

   (4)平均時速は、定常速度の半分くらいで良いと割り切り、普通、急行、
   ロマンスカー等の列車編成の違いも全て無視することにし、さらには、
   乗客の乗降者数についても考えるのを止めて、列車には常に定員が乗車して
   いるという、かなり滅茶苦茶な単純化をしました。

   (5)そして極めつけは、片道運行しかしないという前代未聞の鉄道運行サー
   ビスです。「そんな鉄道、どこのだれが使うか!」というご意見も無視させ
   て頂きます。

   ■「江バ電」のザックリとしたスペック

   1車両=190人。 1構成=8車両 = 1520人
   平均時速 36km/時
   路線距離 100km、平均運行時間:2時間47分(10000秒) 
   運行間隔 10分に1編成 (1日108編成) 
   営業時間 06:00〜24:00(18時間)
   一日あたりの輸送力:16万4160人(片道のみ)

   ■プログラムについての簡単な説明

   単位は秒、メートルで統一、電車は10分単位で出発(車間は6000m)
   車両は同時に16車両程度(100km/6000M= 16.67)

*/

//閉塞区間(概念)
double block_section = 500; // とりあえず500メートル

// 江バ電江端線
double ebata_line = 100000; //路線距離:100.0km

struct train
{
  double distance; // 新宿からの距離(現在距離)
  int line_area_no; // 線区番号
  double speed; // 速度
  int passed_time; // 経過時間
} ;

// 距離は100km, 閉鎖区間は新宿を起点に0.5km(500m)ごと 平均時速36km/h(秒速10メートル)
// 構成数は50車両、
// 閉鎖区間内に別の電車があった場合は、停止する

struct train train[108];  // 一日に運行される編成数

int main()
{

  int head_train_no = 0;  // 初期値
  int tail_train_no = 0;  // 初期値
  int passed_time = 0;

  int accident_seconds = 0; // 事故経過時刻

  printf("%s\t%s\r\n","編成番号","運行時間(秒)");
  printf("========================\r\n");

  while(1){
    // 事故発生ルーチン
    // 列車番号20が、線区20に入ったら、60分(3600秒)間列車を強制的に停止する
    if ((train[20].line_area_no == 20) && (accident_seconds < 3600)){
      train[20].speed = 0.0; // 速度は、ここで強制的に0にする。
      accident_seconds++; //60分を経過するまで、抜けられない
    }

    for (int i = head_train_no; i < tail_train_no; i++){
      // 位置情報更新
      train[i].distance -= train[i].speed * 1.0; // 1秒間に10メートル終着駅に近づく
      train[i].line_area_no = train[i].distance / block_section; // 現在、線区番号
      train[i].passed_time++;
      
      if ( i > head_train_no ){  // 先頭車両は止められない
        if (train[i-1].line_area_no + 1  == train[i].line_area_no){// 前の列車と同じ線区に入ったら、
          train[i].speed = 0.0; // 電車を止めてしまう
        } else { // そうでなければ、
          train[i].speed = 10.0; // 電車を走らせる
        }
      }
    }
    train[head_train_no].speed = 10.0; // 先頭車両は止められない。
    
    // 10分(600秒)単位に、電車を出発させる
    if ((passed_time % 600) == 0){

      if ( tail_train_no <= 108){  // 108構成後は作らない
        
        // 新しい電車の状態
        train[tail_train_no].speed = 10.0;
        train[tail_train_no].distance = ebata_line;
        train[tail_train_no].line_area_no = ebata_line / block_section;
        train[tail_train_no].passed_time = 0;
        
        tail_train_no++;
      }
    }
    
    if (train[head_train_no].distance <= 0.0){ //終着駅に到着したら
      printf("#%3d\t\t%d\r\n",head_train_no,train[head_train_no].passed_time);
      head_train_no++; // その電車は退場
      
      if (head_train_no > 108){  //108番目の電車がついたら、プログラム終了
        printf("========================\r\n");
        exit(0);
      }
    }

    // =========== print section ================

    if ((passed_time % 600) == 0){ // 600秒単位で表示
      
      for (int i = head_train_no; i < tail_train_no; i++){
#if 0 
        printf("train[%d].speed = %f\t", i, train[i].speed);
        printf("train[%d].distance = %f\t", i, train[i].distance);
        printf("train[%d].line_area_no = %d\t", i, train[i].line_area_no);
        printf("\n");
#endif

      }
    }

    // usleep(100); // 0.1秒待つ
    
    passed_time ++; // 秒数加算
    
  }
}