// TrainTimeTable TTT_6.cpp データをファイルから入力する1個列車のN区間の処理

// 線種、加速度、現速度、列車名、走行区間数、始発駅名、始発駅出発時刻(時、分、秒)

// @停車駅名、Aその駅までの区間の制限速度、B始発駅から各停車駅までの距離、C停車時間

// @〜Cの停車駅数分のデータ(終着駅の停車時間は使わないが読み込むのでダミーで0とする)                                  

              

#include<stdio.h>

#include<string.h>

// ---------------------------------- 必要に応じて随時変更 ---------------------------------

const char memo_C[67] ="遅れ発生に対応できるように、所要巡航時間は(制限速度-15)km/hで計算.";

const char memo_S[67] ="停車駅の手前の減速途中で、120km/hで30秒間、45km/hで30秒間定速走行.";

const char memo_Z[32] ="減速の途中 60km/hで30秒間走行.";

// -----------------------------------------------------------------------------------------

//

// ---------------------------------- 関数間で使用する変数 ---------------------------------

char  hatueki[17]  ="                ";// 当該区間の発駅名 (input from file)

char  chakueki[17] ="                ";// 当該区間の着駅名 (input from file)

float hatueki_kyori  = 0.0; // [km] 当該区間発駅の距離座標 (始発駅だけ:input from file)

float chakueki_kyori = 0.0; // [km] 当該区間着駅の距離座標 (input from file)

float ekikan_kyori   = 0.0; // [km]

float seigen_sokudo  = 0.0; // [km/h] 当該区間の制限速度   (input from file)

float kasokudo       = (float)1.8; // [km/h/s] 当該列車の加速度 (input from file)

float kasoku_jikan   = 0.0; // [s]

float kasoku_kyori   = 0.0; // [km]

float gensokudo      = (float)1.5; // [km/h/s] 当該列車の現速度 (input from file)

float gensoku_jikan  = 0.0; // [s]

float gensoku_kyori  = 0.0; // [km]

float junkou_sokudo  = 0.0; // [km/h]

float junkou_jikan   = 0.0; // [s]

float junkou_kyori   = 0.0; // [km]

float ruiseki_jikan  = 0.0; // [s]

float ruiseki_kyori  = 0.0; // [km]

int   teisya_jikan   = 0;   // [s] 着駅での停車時間     (input from file)

float hatu_jikan     = 0.0; // [s] 当該区間の発駅の発車時刻

int   hatu_jikan_h   = 0;   // [h] 始発駅の発車時刻[時] (input from file)

int   hatu_jikan_m   = 0;   // [m] 始発駅の発車時刻[分] (input from file)

int   hatu_jikan_s   = 0;   // [s] 始発駅の発車時刻[秒] (input from file)

float chaku_jikan    = 0.0; // [s] 当該区間の着駅の到着時刻

int   chaku_jikan_h  = 0;   // [h]

int   chaku_jikan_m  = 0;   // [m]

int   chaku_jikan_s  = 0;   // [s]

float ekikan_jikan   = 0.0; // [s]

float ruiseki_yutori_jikan = 0.0; // [s] 累積ゆとり時間

FILE *fpt; // データ入力用のファイル

FILE *fp;  // 結果出力用のファイル

// -----------------------------------------------------------------------------------------

 

int main(){

        char  sen_name[10] = "Sinkansen";      // 新幹線,在来線を区別するためのフラッグ

        int   soukou_kukansuu = 0;             // (input from file)

 

        int   hajime_output(char);

        float input_output(float);             // 独立変数 = 当該列車の発駅の距離

                                                       // 従属変数 = 当該列車の着駅の距離

        float junkou_sokudo_kettei(float);

        void  kasoku_output(void);

        void  gensoku_output(char);

        void  junkou_output(void);

        void  ekikan_output(void);

        void  ruiseki_output(void);

        void  yutori_output(void);

        void  owari_output(void);

 

        fpt = fopen("TTT_2r.dat","r");

        fp  = fopen("TTT_2w.dat","w");

        for(int k=0;k<9;k++){                  // 当該列車の線種を読み込む

                sen_name[k] = getc(fpt);       // Sinkansen or Zairaisen

        }

        soukou_kukansuu = hajime_output(sen_name[0]); 

                                               // 線や列車などの最初の処理

        for(k=0; k < soukou_kukansuu; k++){

                hatueki_kyori = input_output(hatueki_kyori);

                                               // 着駅距離を次の区間の発駅距離に置き換え

                junkou_sokudo = junkou_sokudo_kettei(ekikan_kyori);

                                               // 区間距離に対する巡航速度を決定

                float yutori_sokudo = seigen_sokudo - (float)15.0;

                                               // ダイヤのゆとりの為の減速計算

                if(junkou_sokudo > yutori_sokudo){

                        junkou_sokudo = yutori_sokudo;

                }                              // 区間の制限速度を考慮し巡航速度を修正

                kasoku_output();               // 加速区間に関する処理

                gensoku_output(sen_name[0]);   // 減速区間に関する処理

                junkou_output();               // 巡航区間に関する処理

                ekikan_output();               // 区間全体に関する処理

                ruiseki_output();              // 累積的数値に関する処理

                yutori_output();               // ゆとり時間に関する処理

        }

        owari_output();                        // 評定速度などの最終処理

        fclose(fpt);

        fclose(fp);

        return(1);

}

 

int hajime_output(char flag){

        char  train_name[13] = "            "; // 列車名

        float shihatueki_kyori = (float)0.0;   //

        int   kukansuu = 0;

 

        getc(fpt);                             // 空白文字を読み込んで捨てる

        fscanf(fpt,"%f",&kasokudo);            // 当該列車の通常の加速度を読み込む

        fscanf(fpt,"%f",&gensokudo);           // 当該列車の通常の減速度を読み込む

        getc(fpt);                             // 空白文字を読み込んで捨てる

        for(int k=0;k<12;k++){                 // 当該列車の列車名を読み込む

                train_name[k] = getc(fpt);     //

        }                                 

        fscanf(fpt,"%d",&kukansuu);            // 当該列車の走行区間数を読み込む

        getc(fpt);                             // 空白文字を読み込んで捨てる

        for(k=0;k<16;k++){                     // 当該列車の始発駅名を読み込む

                chakueki[k] = getc(fpt);       //

        }                                 

        fscanf(fpt,"%d %d %d",&hatu_jikan_h,&hatu_jikan_m,&hatu_jikan_s);

                                               // 当該列車の始発駅の出発時間を読み込む

        hatu_jikan = (float)hatu_jikan_h * 3600 + hatu_jikan_m * 60 + hatu_jikan_s;

        fscanf(fpt,"%f",&shihatueki_kyori);    // 当該列車の始発駅の距離を読み込む

        getc(fpt);                             // 改行文字を読み込んで捨てる

        switch(flag){

        case 'S':                              // 新幹線

                printf("--- 新幹線 ---\n");

                printf("            %66s\n", memo_C);   // ゆとり走行の説明を書き込む

                printf("            %66s\n", memo_S);   // 減速方法の説明を書き込む

                fprintf(fp,"--- 新幹線 ---\n");

                fprintf(fp,"            %66s\n", memo_C);

                fprintf(fp,"            %66s\n", memo_S);

                break;

        case 'Z':                              // 在来線

                printf("--- 在来線 ---\n");

                printf("            %66s\n", memo_C);   // ゆとり走行の説明を書き込む

                printf("            %31s\n", memo_Z);   // 減速方法の説明を書き込む

                fprintf(fp,"--- 在来線 ---\n");

                fprintf(fp,"            %66s\n", memo_C);

                fprintf(fp,"            %31s\n", memo_Z);

                break;

        default :

                break;

        }

        hatueki_kyori = shihatueki_kyori;

        printf("\n< %12s >\n\n",train_name);

        fprintf(fp,"\n< %12s >\n\n",train_name);

                return(kukansuu);

}

 

float input_output(float hatueki_kyori){

        int k=0;

 

        for(k=0;k<16;k++){                   // 前区間の着駅名を当該区間の発駅名に

                hatueki[k] = chakueki[k];    //

        }                                                            

        for(k=0;k<16;k++){                   // 当該区間の着駅名を読み込む

                chakueki[k] = getc(fpt);     //

        }                                                   

        fscanf(fpt,"%f",&seigen_sokudo);     // 当該区間の制限速度を読み込む

        printf("%16s %6.1f km ",hatueki,hatueki_kyori);

        printf("----------------------------------------------------\n");

        printf("    %2d:%2d'%2d 発               駅間制限速度= %5.1f km/h\n",

                hatu_jikan_h,hatu_jikan_m,hatu_jikan_s,seigen_sokudo);

        fprintf(fp,"%16s %6.1f km ",hatueki,hatueki_kyori);

        fprintf(fp,"----------------------------------------------------\n");

        fprintf(fp,"    %2d:%2d'%2d 発               駅間制限速度= %5.1f km/h\n",

                hatu_jikan_h,hatu_jikan_m,hatu_jikan_s,seigen_sokudo);

        fscanf(fpt,"%f",&chakueki_kyori);    // 当該区間着駅の着時刻を読み込む

        fscanf(fpt,"%d",&teisya_jikan);      // 着駅での停車時間を読み込む

        getc(fpt);                           // 改行文字を読み込んで捨てる

        ekikan_kyori = chakueki_kyori - hatueki_kyori;  // 当該区間の距離を計算

        return(chakueki_kyori);

}

 

float junkou_sokudo_kettei(float kyori){

        float sokudo=1.0; // [km/h]

 

        if     (kyori>=30.0)sokudo=285.0;

        else if(kyori>=25.0)sokudo=265.0;

        else if(kyori>=20.0)sokudo=245.0;

        else if(kyori>=15.0)sokudo=225.0;

        else if(kyori>=10.0)sokudo=205.0;

        else if(kyori>= 7.0)sokudo=185.0;

        else if(kyori>= 5.0)sokudo=165.0;

        else if(kyori>= 4.0)sokudo=145.0;

        else if(kyori>= 3.0)sokudo=125.0;

        else if(kyori>= 2.5)sokudo=110.0;

        else if(kyori>= 2.0)sokudo= 95.0;

        else if(kyori>= 1.5)sokudo= 80.0;

        else if(kyori>= 1.0)sokudo= 65.0;

        else if(kyori>= 0.5)sokudo= 45.0;

        else printf("kyori error");

        return(sokudo);

}

 

void kasoku_output(){

        int kasoku_jikan_m =0; // [m]

        int kasoku_jikan_s =0; // [s]

       

        kasoku_jikan   = junkou_sokudo / kasokudo;

        kasoku_jikan_m = (long)kasoku_jikan / 60;

        kasoku_jikan_s = (long)kasoku_jikan % 60;

        kasoku_kyori   = (junkou_sokudo / (float)2.0) * (kasoku_jikan / (float)3600.0);

        printf("                  加 速 度 =%3.1f km/h/s,",kasokudo);

        printf("  加速時間 =%3dm%2ds,",kasoku_jikan_m,kasoku_jikan_s);

        printf("  加速距離 =%5.1f km\n",kasoku_kyori);

        fprintf(fp,"                  加 速 度 =%3.1f km/h/s,",kasokudo);

        fprintf(fp,"  加速時間 =%3dm%2ds,",kasoku_jikan_m,kasoku_jikan_s);

        fprintf(fp,"  加速距離 =%5.1f km\n",kasoku_kyori);

}

 

void gensoku_output(char flag){

        float gensoku_jikan_A =0.0; // [s] ストレートに0km/hまで減速する場合の減速時間

        int   gensoku_jikan_m =0;   // [m]

        int   gensoku_jikan_s =0;   // [s]

 

        gensoku_jikan_A = junkou_sokudo / gensokudo;

        switch(flag){

        case 'S':

            if(junkou_sokudo > 120){

                gensoku_jikan = gensoku_jikan_A + (float)60.0;

                gensoku_kyori = (junkou_sokudo / (float)2.0) * (gensoku_jikan_A / (float)3600.0) + (float)1.375;

            }

            else if(junkou_sokudo > 45){

                gensoku_jikan = gensoku_jikan_A + (float)30.0;

                gensoku_kyori = (junkou_sokudo / (float)2.0) * (gensoku_jikan_A / (float)3600.0) + (float)0.375;

            }

            else{

                gensoku_jikan = gensoku_jikan_A;

                gensoku_kyori = (junkou_sokudo / (float)2.0) * (gensoku_jikan_A / (float)3600.0);

            }

            break;

        case 'Z':

            if(junkou_sokudo > 60){

                gensoku_jikan = gensoku_jikan_A + (float)30.0;

                gensoku_kyori = (junkou_sokudo / (float)2.0) * (gensoku_jikan_A / (float)3600.0) + (float)0.5;

            }

            else{

                gensoku_jikan = gensoku_jikan_A;

                gensoku_kyori = (junkou_sokudo / (float)2.0) * (gensoku_jikan_A / (float)3600.0);

            }

            break;

        default:

            break;

        }

        gensoku_jikan_m = (long)gensoku_jikan / 60;

        gensoku_jikan_s = (long)gensoku_jikan % 60;

        printf("                  減 速 度 =%3.1f km/h/s,",gensokudo);

        printf("  減速時間 =%3dm%2ds,",gensoku_jikan_m,gensoku_jikan_s);

        printf("  減速距離 =%5.1f km\n",gensoku_kyori);

        fprintf(fp,"                  減 速 度 =%3.1f km/h/s,",gensokudo);

        fprintf(fp,"  減速時間 =%3dm%2ds,",gensoku_jikan_m,gensoku_jikan_s);

        fprintf(fp,"  減速距離 =%5.1f km\n",gensoku_kyori);

}

 

void junkou_output(){

        int junkou_jikan_m = 0; // [m]

        int junkou_jikan_s = 0; // [s]

 

        junkou_kyori = ekikan_kyori - kasoku_kyori - gensoku_kyori;

        junkou_jikan = (junkou_kyori / junkou_sokudo) * (float)3600.0;

        junkou_jikan_m = (long)junkou_jikan / 60;

        junkou_jikan_s = (long)junkou_jikan % 60;

        printf("                  巡航速度 =%5.1f km/h,",junkou_sokudo);

        printf("  巡航時間 =%3dm%2ds,",junkou_jikan_m,junkou_jikan_s);

        printf("  巡航距離 =%5.1f km\n",junkou_kyori);

        fprintf(fp,"                  巡航速度 =%5.1f km/h,",junkou_sokudo);

        fprintf(fp,"  巡航時間 =%3dm%2ds,",junkou_jikan_m,junkou_jikan_s);

        fprintf(fp,"  巡航距離 =%5.1f km\n",junkou_kyori);

}

 

void ekikan_output(){

        float heikin_sokudo  = 0.0; // [km/h]

        int   ekikan_jikan_m = 0;   // [m]

        int   ekikan_jikan_s = 0;   // [s]

 

        ekikan_jikan = kasoku_jikan + gensoku_jikan + junkou_jikan;

        ekikan_jikan_m = (long)ekikan_jikan / 60;

        ekikan_jikan_s = (long)ekikan_jikan % 60;

        heikin_sokudo = ekikan_kyori / (ekikan_jikan / (float)3600.0);

        printf("                  平均速度 =%5.1f km/h,  ",heikin_sokudo);

        printf("駅間時間 =%3dm%2ds,  ",ekikan_jikan_m, ekikan_jikan_s);

        printf("駅間距離 =%5.1f km\n",ekikan_kyori);

        fprintf(fp,"                  平均速度 =%5.1f km/h,  ",heikin_sokudo);

        fprintf(fp,"駅間時間 =%3dm%2ds,  ",ekikan_jikan_m, ekikan_jikan_s);

        fprintf(fp,"駅間距離 =%5.1f km\n",ekikan_kyori);

} 

 

void ruiseki_output(){

        int ruiseki_jikan_h = 0; // [h]

        int ruiseki_jikan_m = 0; // [m]

        int ruiseki_jikan_s = 0; // [s]

 

        chaku_jikan = hatu_jikan + ekikan_jikan;

        chaku_jikan_h = (long)chaku_jikan / 3600;

        chaku_jikan_m = ((long)chaku_jikan % 3600) / 60;

        chaku_jikan_s = (long)chaku_jikan % 60;

        ruiseki_jikan += ekikan_jikan;

        ruiseki_jikan_h = (long)ruiseki_jikan / 3600;

        ruiseki_jikan_m = ((long)ruiseki_jikan % 3600) / 60;

        ruiseki_jikan_s = (long)ruiseki_jikan % 60;

        printf("    %2d:%2d'%2d 着               累積所要時間 =%2dh%2dm%2ds,",

                   chaku_jikan_h,chaku_jikan_m,chaku_jikan_s, ruiseki_jikan_h,ruiseki_jikan_m,ruiseki_jikan_s);

        fprintf(fp,"    %2d:%2d'%2d 着                   累積時間 =%2dh%2dm%2ds,",

                   chaku_jikan_h,chaku_jikan_m,chaku_jikan_s, ruiseki_jikan_h,ruiseki_jikan_m,ruiseki_jikan_s);

        ruiseki_jikan += (float)teisya_jikan;

        ruiseki_kyori += ekikan_kyori;

        hatu_jikan = chaku_jikan + (float)teisya_jikan;

        hatu_jikan_h = (long)hatu_jikan / 3600;

        hatu_jikan_m = ((long)hatu_jikan % 3600) / 60;

        hatu_jikan_s = (long)hatu_jikan % 60;

 }

 

void yutori_output(){

        float saitan_junkou_jikan = 0.0; // [s]

        float yutori_jikan        = 0.0; // [s]

        int   yutori_jikan_m      = 0;   // [m]

        int   yutori_jikan_s      = 0;   // [s]

 

        saitan_junkou_jikan = junkou_kyori / seigen_sokudo * 3600;

        yutori_jikan   = junkou_jikan - saitan_junkou_jikan;

        yutori_jikan_m = (long)yutori_jikan / 60;

        yutori_jikan_s = (long)yutori_jikan % 60;

        printf("   駅間ゆとり時間 =%2dm%2ds\n",yutori_jikan_m,yutori_jikan_s);

        fprintf(fp,"   駅間ゆとり時間 =%2dm%2ds\n",yutori_jikan_m,yutori_jikan_s);

        ruiseki_yutori_jikan += yutori_jikan;

}

 

void owari_output(){

        float hyoutei_sokudo = 0.0;       // [km/h]

        int   ruiseki_yutori_jikan_m = 0; // [m]

        int   ruiseki_yutori_jikan_s = 0; // [s]

 

        hyoutei_sokudo = ruiseki_kyori / (ruiseki_jikan / 3600);

        ruiseki_yutori_jikan_m = (long)ruiseki_yutori_jikan / 60;

        ruiseki_yutori_jikan_s = (long)ruiseki_yutori_jikan % 60;

        printf("%16s %6.1f km",chakueki,chakueki_kyori);

        printf(" ----------------------------------------------------\n");

        printf("                              評定速度 =%5.1f km/h,      累積ゆとり時間 =%2dm%2ds\n\n",

                             hyoutei_sokudo, ruiseki_yutori_jikan_m, ruiseki_yutori_jikan_s);

        fprintf(fp,"%16s %6.1f km",chakueki,chakueki_kyori);

        fprintf(fp," ----------------------------------------------------\n");

        fprintf(fp,"                              評定速度 =%5.1f km/h,      累積ゆとり時間 =%2dm%2ds\n\n",

                             hyoutei_sokudo, ruiseki_yutori_jikan_m, ruiseki_yutori_jikan_s);

}