#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <unistd.h> // usleep関数を使用
#define NUM_ROUTES 20
#define PI 3.14159265358979323846
#define EARTH_RAD 6378.137 // km
#define NUM_SHIPS 200

void correct_time_format(const char *time_str, char *corrected_time);

int global_ship_id = 1; // グローバルで一意な船舶IDを保持

typedef struct
{
    double x, y;
} Point;

typedef struct
{
    Point start, end;
} Segment;

typedef struct
{
    char name[16];        // ゲート名
    Segment segment;      // ゲートの開始点と終了点
    double mean;          // 通過位置の平均値
    double std;           // 通過位置の標準偏差
    double speed_mean;    // 速度の平均
    double speed_std;     // 速度の標準偏差
    double ship_gen_mean; // 船舶生成数の平均（追加）
    double ship_gen_std;  // 船舶生成数の標準偏差（追加）
    double averages[24];  // 時間ごとの通過平均
} Gate;

typedef struct
{
    int seconds;
    double latitude;
    double longitude;
    double heading;
    double speed;
    double size;
    int ship_id;
    char next_gate_name[32];
} Record;

// グローバルスコープ
Record records[1000000];
int record_count = 0;

Record temp_records[1000000];

// 配列の要素数を取得するマクロ
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

// 0から1までの一様乱数を生成
double urand()
{
    return (double)rand() / RAND_MAX;
}

double rand_normal(double mu, double sigma)
{
    double u1 = urand();
    double u2 = urand();

    // ボックス＝ミュラー法
    double z = sqrt(-2.0 * log(u1)) * cos(2.0 * M_PI * u2);

    // 極端な値を制限
    double result = mu + sigma * z;
    if (result < mu - 4 * sigma)
        result = mu - 4 * sigma; // 下限
    if (result > mu + 4 * sigma)
        result = mu + 4 * sigma; // 上限
    return result;
}

// 範囲[a, b]の一様分布に従う乱数を生成
double rand_uniform(double a, double b)
{
    return a + (b - a) * urand();
}

// 重み付き確率に基づいてインデックスを選択
int weighted_choice(double *weights, int size)
{
    double total_weight = 0;
    for (int i = 0; i < size; i++)
    {
        total_weight += weights[i];
    }

    double r = urand() * total_weight; // 0から総重みまでの乱数を生成
    double sum = 0;
    for (int i = 0; i < size; i++)
    {
        sum += weights[i];
        if (r <= sum)
        {
            return i; // 重みに基づいて選ばれたインデックスを返す
        }
    }
    return size - 1; // 万が一のためのフォールバック
}

// correct_time_format 関数の定義
void correct_time_format(const char *time_str, char *corrected_time)
{
    int h, m, s;

    // 時間をパース
    if (sscanf(time_str, "%d:%d:%d", &h, &m, &s) == 3)
    {
        // 総秒数を計算
        int total_seconds = h * 3600 + m * 60 + s;

        // 時間、分、秒に戻す
        h = (total_seconds / 3600) % 24;
        m = (total_seconds % 3600) / 60;
        s = total_seconds % 60;

        // 修正された時間をフォーマット
        sprintf(corrected_time, "%02d:%02d:%02d", h, m, s);
    }
    else
    {
        // フォーマットが不正の場合はそのまま返す
        strcpy(corrected_time, time_str);
    }
}

// 船舶の大きさを累積確率に基づいて生成する関数
double generate_random_size()
{
    // 全長範囲とその割合の累積確率
    double length_ranges[8][2] = {
        {0, 20}, {20, 50}, {50, 100}, {100, 150}, {150, 200}, {200, 250}, {250, 300}, {300, 400} // 最後は「その他」として300m以上に対応
    };

    // 各範囲の割合（累積確率）
    double cumulative_probabilities[] = {
        0.022, // 0-20: 2.2%
        0.103, // 20-50: 8.1%
        0.334, // 50-100: 23.1%
        0.652, // 100-150: 31.8%
        0.868, // 150-200: 21.6%
        0.928, // 200-250: 6.0%
        0.953, // 250-300: 2.5%
        1.000  // 300以上: 4.7%
    };

    double r = urand(); // 一様乱数を生成

    // 累積確率に基づいて長さを選ぶ
    for (int i = 0; i < 8; i++)
    {
        if (r <= cumulative_probabilities[i])
        {
            // 該当する範囲内のランダムな値を返す
            return rand_uniform(length_ranges[i][0], length_ranges[i][1]);
        }
    }
    return 0; // デフォルトの値（ここには到達しないはず）
}

// 度（degrees）をラジアン（radians）に変換するプロトタイプ宣言
double deg2rad(double deg);

double calculate_heading(Point start, Point end)
{
    double lat1 = deg2rad(start.y);
    double lat2 = deg2rad(end.y);
    double lon1 = deg2rad(start.x);
    double lon2 = deg2rad(end.x);
    double delta_lon = lon2 - lon1;

    double y = sin(delta_lon) * cos(lat2);
    double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_lon);

    double heading = atan2(y, x);       // ラジアン
    heading = heading * (180.0 / M_PI); // 度に変換
    if (heading < 0)
        heading += 360.0; // 0-360度に補正
    return heading;
}

// ランダムな点を生成
void generate_random_point(Segment seg, Point *p, double mu, double sigma, int use_uniform)
{
    double length_x = seg.end.x - seg.start.x;
    double length_y = seg.end.y - seg.start.y;

    double rand_value;

    if (use_uniform)
    {
        rand_value = rand_uniform(0, 1); // 一様乱数
    }
    else
    {
        rand_value = rand_normal(mu, sigma);       // 正規乱数
        rand_value = fmin(fmax(rand_value, 0), 1); // 0から1の範囲に制限
    }
    p->x = seg.start.x + length_x * rand_value;
    p->y = seg.start.y + length_y * rand_value;
}

double cal_distance(Point p1, Point p2);                     // 2点間の地球上の距離を計算
int calculate_seconds(Point start, Point end, double speed); // 2点間の移動にかかる時間を計算

void correct_time_format(const char *time_str, char *corrected_time);

// 船舶の情報を書き込む関数（船舶ID, x座標, y座標, 時刻, 船舶の大きさ, 速力, 次のゲート名）
// 船舶データの記録関数
void record_ship_positions(int ship_id, Point start, Point *end, double speed, double ship_size, int start_seconds, const char *color, const char *next_gate_name)
{
    double distance = cal_distance(start, *end);
    int total_seconds = calculate_seconds(start, *end, speed);
    double heading = calculate_heading(start, *end); // 針路計算

    Point current_position;

    for (int elapsed_seconds = 0; elapsed_seconds < total_seconds; elapsed_seconds ++)
    {
        double ratio = (double)elapsed_seconds / total_seconds; // 線形補間の比率
        current_position.x = start.x + ratio * (end->x - start.x);
        current_position.y = start.y + ratio * (end->y - start.y);

        // 現在の時刻を計算
        int current_second = start_seconds + elapsed_seconds;

        // 通常の記録処理
        if (record_count < 1000000)
        {
            Record *record = &records[record_count++];
            record->seconds = current_second;
            record->latitude = current_position.y;
            record->longitude = current_position.x;
            record->heading = heading;
            record->speed = speed;
            record->size = ship_size;
            record->ship_id = ship_id;
            strcpy(record->next_gate_name, next_gate_name);
        }
        else
        {
            fprintf(stderr, "Error: Record array is full.\n");
        }
    }

    end->x = current_position.x;
    end->y = current_position.y;
}

// 度（degrees）をラジアン（radians）に変換
double deg2rad(double deg)
{
    return deg * M_PI / 180.0;
}

// 2点間の地球上の距離を中分緯度航法を用いて計算
double cal_distance(Point p1, Point p2)
{
    double lat1 = deg2rad(p1.y);
    double lat2 = deg2rad(p2.y);
    double lon1 = deg2rad(p1.x);
    double lon2 = deg2rad(p2.x);

    double dLat = lat2 - lat1;
    double dLon = lon2 - lon1;

    double a = sin(dLat / 2) * sin(dLat / 2) +
               cos(lat1) * cos(lat2) *
                   sin(dLon / 2) * sin(dLon / 2);
    double c = 2 * atan2(sqrt(a), sqrt(1 - a));

    double R = EARTH_RAD;    // 地球の半径 (km)
    double distance = R * c; // 距離を計算

    return distance;
}

// 2点間の移動にかかる時間を計算
int calculate_seconds(Point start, Point end, double speed)
{
    double distance = cal_distance(start, end);
    return distance / (speed * 1.852) * 3600;
}

// 時間文字列を秒に変換する関数
int time_to_seconds(const char *time)
{
    int hours, minutes, seconds;
    sscanf(time, "%d:%d:%d", &hours, &minutes, &seconds);
    return hours * 3600 + minutes * 60 + seconds;
}

void seconds_to_time(int seconds, char *corrected_time)
{
    seconds = seconds % 86400;
    int hours = seconds / 3600;
    int minutes = (seconds % 3600) / 60;
    int remaining_seconds = seconds % 60;
    sprintf(corrected_time, "%02d:%02d:%02d", hours, minutes, remaining_seconds);
}

void fill_empty_records(int record_seconds)
{
    char corrected_time[16];
    seconds_to_time(record_seconds, corrected_time);

    // 既存レコードとの重複を確認
    for (int i = 0; i < record_count; i++)
    {
        if (records[i].seconds == record_seconds)
        {
            return;
        }
    }

    // 既存レコードがない場合のみ空白を挿入
    if (record_count < 1000000)
    {
        Record *record = &records[record_count++];
        record->seconds = record_seconds;
        record->latitude = 0;  // 空の値（必要に応じて変更可能）
        record->longitude = 0; // 空の値（必要に応じて変更可能）
        record->heading = 0;
        record->speed = 0;
        record->size = 0;
        record->ship_id = 0; // 特別なID（例えば-1）で空欄を示す
        strcpy(record->next_gate_name, "NONE");
    }
    else
    {
        fprintf(stderr, "Error: Record array is full.\n");
        return;
    }
}

int generate_ships_based_on_normal_distribution(int hour, Gate *start_gates, int start_gate_size)
{
    int ship_count = 0;
    // すべての各ゲートで発生する船舶の数を計算
    for (int i = 0; i < start_gate_size; i++)
    {
        ship_count += rand_normal(start_gates[i].averages[hour], start_gates[i].ship_gen_std);
    }
    return ship_count;
}

int main()
{
    // セグメント（ゲート）定義
    Gate gateA = {
        "gateA",
        {{28.994180, 40.990570}, {28.989140, 40.990570}},
        0.3795123751414109,
        0.1214,
        9.8,
        2.2,
        49.3,
        18.4,
        {2.2, 1.4, 1.4, 1.6, 1.0, 1.0, 1.0, 0.8, 1.4, 1.5, 1.5, 1.8,
         2.5, 3.4, 3.3, 3.1, 3.0, 3.4, 3.2, 3.4, 2.6, 2.8, 1.9, 2.2}};
    Gate gateAA = {
        "gateAA",
        {{28.994180, 40.990570}, {29.000300, 40.990570}},
        0.27494616772958225,
        0.1075,
        8.7,
        2.9, // 平均8.7ノット、標準偏差2.9ノット
        51.3,
        20.5,
        {1.7, 1.5, 1.6, 1.8, 1.0, 1.2, 1.1, 1.5, 1.4, 1.6, 2.0, 2.4,
         2.8, 3.5, 3.8, 4.0, 3.2, 3.7, 3.9, 4.1, 2.8, 3.1, 2.5, 3.0}};
    Gate gateB = {
        "gateB",
        {{28.978720, 40.984520}, {28.989980, 40.979040}},
        0.3611126190752607,
        0.147,
        10.0,
        3.6, // 平均10.0ノット、標準偏差3.6ノット
        52.6,
        21.6,
        {1.8, 1.7, 2.4, 2.6, 3.2, 2.8, 2.9, 2.9, 3.0, 3.0, 3.2, 2.9,
         2.4, 1.7, 1.4, 1.4, 1.8, 1.7, 2.1, 1.8, 1.7, 1.5, 1.3, 1.5}};
    Gate gateBB = {
        "gateBB",
        {{28.989980, 40.979040}, {29.000300, 40.978270}},
        0.3636974171854326,
        0.19,
        8.3,
        3.3, // 平均8.3ノット、標準偏差3.3ノット
        54.2,
        22.0,
        {2.3, 1.5, 1.5, 1.5, 1.0, 1.0, 1.0, 1.0, 1.3, 1.4, 1.7, 2.2,
         2.8, 3.5, 3.4, 3.8, 3.3, 3.6, 3.8, 3.5, 2.7, 2.8, 2.0, 2.5}};
    Gate gateC = {
        "gateC",
        {{28.952974, 40.969207}, {28.967805, 40.962041}},
        0.34069541917751117,
        0.1781,
        10.8,
        5.7, // 平均10.8ノット、標準偏差5.7ノット
        45.3,
        17.9,
        {1.4, 1.5, 1.7, 2.1, 2.4, 2.7, 2.3, 3.0, 2.5, 2.7, 2.4, 2.3,
         1.8, 1.6, 1.4, 0.8, 1.4, 2.0, 1.7, 2.1, 1.5, 1.4, 1.0, 1.5}};
    Gate gateCC = {
        "gateCC",
        {{28.976520, 40.957949}, {29.000300, 40.946212}},
        0.33760915478452064,
        0.1307,
        8.8,
        5.7, // 平均8.8ノット、標準偏差5.7ノット
        54.6,
        19.7,
        {2.1, 1.6, 2.1, 1.4, 1.2, 1.2, 1.0, 2.2, 2.4, 2.7, 2.7, 2.7,
         2.9, 3.8, 3.7, 3.4, 3.4, 4.2, 3.9, 3.5, 3.2, 3.4, 3.0, 2.6}};
    Gate gateD = {
        "gateD",
        {{28.903138, 40.946207}, {28.952974, 40.969207}},
        0.36794637500286187,
        0.12265,
        7.9,
        4.8, // 平均7.9ノット、標準偏差4.8ノット
        20.9,
        5.1,
        {0.7, 0.3, 0.4, 0.5, 0.5, 0.8, 0.7, 0.7, 1.2, 1.5, 1.0, 1.1,
         1.0, 1.6, 1.0, 1.0, 1.0, 1.0, 1.2, 1.4, 1.0, 0.7, 0.7, 1.0}};
    Gate gateE = {
        "gateE",
        {{29.000300, 40.946212}, {29.000307, 40.915708}},
        0.34309599909910935,
        0.1556,
        17.6,
        5.9, // 平均17.6ノット、標準偏差5.9ノット
        7.6,
        2.5,
        {0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.0, 0.1, 0.1, 0.3, 0.5, 0.2,
         0.7, 0.5, 0.7, 0.1, 0.8, 0.3, 0.7, 0.4, 0.6, 0.5, 0.4, 0.1}};
    Gate gateF = {
        "gateF",
        {{28.903138, 40.946207}, {28.912969, 40.925369}},
        0.3773789888368554,
        0.1546,
        9.1,
        4.1, // 平均9.1ノット、標準偏差4.1ノット
        48.5,
        17.8,
        {1.6, 2.0, 1.7, 2.1, 2.4, 2.1, 2.0, 2.4, 2.3, 2.5, 2.3, 2.5,
         2.0, 2.4, 2.0, 1.5, 1.7, 1.7, 1.6, 2.4, 2.0, 1.7, 1.6, 2.1}};
    Gate gateFF = {
        "gateFF",
        {{28.922640, 40.904040}, {28.931308, 40.880708}},
        0.3704055684657731,
        0.1182,
        10.3,
        5.7, // 平均10.3ノット、標準偏差5.7ノット
        36.4,
        12.3,
        {0.5, 0.5, 0.4, 0.5, 1.0, 0.6, 0.5, 0.6, 0.8, 0.7, 0.6, 0.7,
         0.6, 0.8, 0.5, 0.7, 0.2, 0.4, 0.5, 0.5, 0.3, 0.4, 0.4, 0.6}};
    Gate gateG = {
        "gateG",
        {{28.931308, 40.880708}, {28.951810, 40.895369}},
        0.44943126481021567,
        0.1927,
        9.7,
        4.2, // 平均9.7ノット、標準偏差4.2ノット
        13.0,
        5.4,
        {0.6, 0.4, 0.5, 0.4, 1.0, 0.1, 0.3, 0.5, 0.5, 0.5, 1.0, 1.3,
         1.3, 0.8, 1.0, 0.9, 1.0, 1.7, 1.5, 1.3, 0.8, 1.2, 0.9, 1.0}};
    Gate gateH = {
        "gateH",
        {{29.000307, 40.915708}, {28.975142, 40.910705}},
        0.4509675842148985,
        0.1062,
        9.2,
        4.1, // 平均9.2ノット、標準偏差4.1ノット
        18.8,
        6.5,
        {1.4, 1.7, 1.5, 1.9, 2.0, 1.8, 1.7, 1.7, 1.7, 2.1, 2.3, 2.2,
         2.2, 2.0, 1.6, 1.6, 1.8, 2.1, 1.5, 2.4, 1.5, 1.5, 1.5, 1.6}};
    Gate gateI = {
        "gateI",
        {{28.867470, 40.930540}, {28.867640, 40.897370}},
        0.30158689333871064,
        0.1912,
        10.2,
        4.0, // 平均10.2ノット、標準偏差4.0ノット
        44.5,
        13.9,
        {0.8, 0.8, 1.0, 0.6, 1.2, 1.4, 1.4, 1.4, 1.8, 1.8, 1.2, 1.4,
         2.1, 1.8, 1.5, 1.0, 1.4, 1.7, 1.4, 1.3, 0.8, 1.2, 1.0, 0.8}};
    Gate gateII = {
        "gateII",
        {{28.867140, 40.838870}, {28.867640, 40.872369}},
        0.49875591093719296,
        0.10435,
        9.7,
        3.1, // 平均9.7ノット、標準偏差3.1ノット
        30.8,
        7.2,
        {0.5, 0.5, 0.4, 0.5, 0.5, 0.6, 0.5, 0.6, 0.5, 0.5, 0.5, 0.5,
         0.5, 0.5, 0.5, 0.7, 0.5, 0.5, 0.5, 0.5, 0.3, 0.5, 0.2, 0.5}};
    Gate gateJ = {
        "gateJ",
        {{28.965980, 40.864870}, {28.942140, 40.857370}},
        0.45039566405729986,
        0.1451,
        8.8,
        3.2, // 平均8.8ノット、標準偏差3.2ノット
        11.1,
        4.9,
        {0.4, 0.5, 0.3, 0.3, 0.3, 0.1, 0.4, 0.4, 0.4, 0.4, 0.4, 0.9,
         0.9, 1.4, 1.4, 0.8, 1.0, 1.4, 1.3, 1.0, 0.9, 1.0, 0.6, 0.7}};
    Gate gateL = {
        "gateL",
        {{29.028150, 40.865710}, {29.004480, 40.857370}},
        0.4941690068149443,
        0.1991,
        9.3,
        3.4, // 平均9.3ノット、標準偏差3.4ノット
        16.0,
        6.1,
        {0.5, 0.5, 0.4, 0.5, 0.5, 0.6, 0.5, 0.6, 0.8, 0.7, 0.6, 0.7,
         0.6, 0.8, 0.5, 0.7, 0.2, 0.4, 0.5, 0.5, 0.3, 0.4, 0.4, 0.6}};
    Gate roundabout1 = {
        "roundabout1",
        {{28.9500, 40.9350}, {28.967805, 40.962041}},
        0.55,
        0.11,
        -1,
        -1};
    Gate roundabout12 = {
        "roundabout1",
        {{28.9500, 40.9350}, {28.967805, 40.962041}},
        0.1,
        0.1,
        -1,
        -1};
    Gate roundabout2 = {
        "roundabout2",
        {{28.9500, 40.9350}, {28.952974, 40.969207}},
        0.61,
        0.11,
        -1,
        -1};
    Gate roundabout3 = {
        "roundabout3",
        {{28.9500, 40.9350}, {28.903138, 40.946207}},
        0.62,
        0.1,
        -1,
        -1};
    Gate roundabout33 = {
        "roundabout3",
        {{28.9500, 40.9350}, {28.903138, 40.946207}},
        0.25,
        0.1,
        -1,
        -1};
    Gate roundabout35 = {
        "roundabout3",
        {{28.9500, 40.9350}, {28.903138, 40.946207}},
        0.2,
        0.11,
        -1,
        -1};
    Gate roundabout4 = {
        "roundabout4",
        {{28.9500, 40.9350}, {28.912969, 40.925369}},
        0.5,
        0.11,
        -1,
        -1};
    Gate roundabout5 = {
        "roundabout5",
        {{28.9500, 40.9350}, {28.922640, 40.904040}},
        0.6,
        0.11,
        -1,
        -1};
    Gate roundabout55 = {
        "roundabout3",
        {{28.9500, 40.9350}, {28.922640, 40.904040}},
        0.1,
        0.1,
        -1,
        -1};
    Gate roundabout6 = {
        "roundabout6",
        {{28.9500, 40.9350}, {28.931308, 40.880708}},
        0.55,
        0.11,
        -1,
        -1};
    Gate roundabout7 = {
        "roundabout7",
        {{28.9500, 40.9350}, {28.951810, 40.895369}},
        0.57,
        0.11,
        -1,
        -1};
    Gate roundabout75 = {
        "roundabout3",
        {{28.9500, 40.9350}, {28.951810, 40.895369}},
        0.1,
        0.1,
        -1,
        -1};
    Gate roundabout8 = {
        "roundabout8",
        {{28.9500, 40.9350}, {28.975142, 40.910705}},
        0.57,
        0.11,
        -1,
        -1};
    Gate roundabout85 = {
        "roundabout8",
        {{28.9500, 40.9350}, {28.975142, 40.910705}},
        0.25,
        0.11,
        -1,
        -1};
    Gate roundabout9 = {
        "roundabout9",
        {{28.9500, 40.9350}, {29.000307, 40.915708}},
        0.48,
        0.11,
        -1,
        -1};
    Gate roundabout95 = {
        "roundabout9",
        {{28.9500, 40.9350}, {29.000307, 40.915708}},
        0.2,
        0.1,
        -1,
        -1};
    Gate roundabout10 = {
        "roundabout10",
        {{28.9500, 40.9350}, {29.000300, 40.946212}},
        0.6,
        0.11,
        -1,
        -1};
    Gate roundabout13 = {
        "roundabout3",
        {{28.9500, 40.9350}, {29.000300, 40.946212}},
        0.2,
        0.1,
        -1,
        -1};
    Gate roundabout15 = {
        "roundabout3",
        {{28.9500, 40.9350}, {29.000300, 40.946212}},
        0.2,
        0.1,
        -1,
        -1};
    Gate roundabout11 = {
        "roundabout11",
        {{28.9500, 40.9350}, {28.976520, 40.957949}},
        0.55,
        0.11,
        -1,
        -1};
    Gate roundabout17 = {
        "roundabout11",
        {{28.9500, 40.9350}, {28.976520, 40.957949}},
        0.2,
        0.11,
        -1,
        -1};

    Gate route1[] = {gateA, gateB, gateC, gateD};
    Gate route2[] = {gateA, gateB, gateC, gateF, gateI};
    Gate route3[] = {gateA, gateB, gateC, roundabout33, gateG, gateJ};
    Gate route4[] = {gateA, gateB, gateC, roundabout3, roundabout7, gateE};
    Gate route5[] = {gateD, gateF, gateI};
    Gate route6[] = {gateD, roundabout6, gateG, gateJ};
    Gate route7[] = {gateD, roundabout6, gateE};
    Gate route8[] = {gateD, roundabout35, roundabout95, gateCC, gateBB, gateAA};
    Gate route9[] = {gateII, gateFF, gateG, gateJ};
    Gate route10[] = {gateII, gateFF, roundabout7, roundabout85, roundabout17, gateD};
    Gate route11[] = {gateII, gateFF, roundabout6, gateE};
    Gate route12[] = {gateII, gateFF, roundabout8, gateCC, gateBB, gateAA};
    Gate route13[] = {gateL, gateH, gateE};
    Gate route14[] = {gateL, gateH, gateCC, gateBB, gateAA};
    Gate route15[] = {gateL, gateH, roundabout12, gateD};
    Gate route16[] = {gateL, gateH, roundabout13, gateF, gateI};
    Gate route17[] = {gateE, gateCC, gateBB, gateAA};
    Gate route18[] = {gateE, roundabout1, gateD};
    Gate route19[] = {gateE, roundabout2, gateF, gateI};
    Gate route20[] = {gateE, roundabout12, roundabout55, gateG, gateJ};

    double route_weights[] = {
        5.26, 38.26, 5.96, 0.00,
        3.15, 1.51, 0.00, 5.84,
        3.13, 3.75, 0.00, 27.37,
        0.00, 10.14, 3.39, 4.19,
        9.31, 0.00, 0.00, 0.37};
    const char *route_colors[] = {"red", "red", "red", "red", "green", "green", "green", "blue", "green", "green", "green", "blue", "green", "blue", "green", "green", "blue", "green", "green", "green"};

    Gate start_gates[] = {gateA, gateD, gateII, gateL, gateE};

    srand(time(NULL));

    // 記録開始時間（例: 10:00:00）
    int start_seconds = time_to_seconds("00:00:00");
    int seconds = start_seconds;
    double ship_gen_count = 0;

    while (1)
    {
        // 他のゲートも同様に設定
        Gate gates[] = {gateA, gateD, gateE, gateII, gateL};
        int num_gates = sizeof(gates) / sizeof(gates[0]);

        ship_gen_count += generate_ships_based_on_normal_distribution((seconds / 3600) % 24, start_gates, ARRAY_SIZE(start_gates)) / 3600.;
        int total_ships = 0;

        while (ship_gen_count > 1)
        {
            ship_gen_count -= 1;
            total_ships += 1;
        }

        for (int i = 0; i < total_ships; i++)
        {
            int route_index = weighted_choice(route_weights, NUM_ROUTES);
            Gate *route;
            Point last_point;
            int num_segments;
            double ship_size = generate_random_size(); // 船舶の大きさをルート全体で一貫させる
            double speed;
            int ship_seconds;

            int current_ship_id = global_ship_id++;

            //usleep(1000000); // 0.1秒の遅延
            switch (route_index)
            {
            case 0:
                route = route1;
                num_segments = ARRAY_SIZE(route1);
                break;
            case 1:
                route = route2;
                num_segments = ARRAY_SIZE(route2);
                break;
            case 2:
                route = route3;
                num_segments = ARRAY_SIZE(route3);
                break;
            case 3:
                route = route4;
                num_segments = ARRAY_SIZE(route4);
                break;
            case 4:
                route = route5;
                num_segments = ARRAY_SIZE(route5);
                break;
            case 5:
                route = route6;
                num_segments = ARRAY_SIZE(route6);
                break;
            case 6:
                route = route7;
                num_segments = ARRAY_SIZE(route7);
                break;
            case 7:
                route = route8;
                num_segments = ARRAY_SIZE(route8);
                break;
            case 8:
                route = route9;
                num_segments = ARRAY_SIZE(route9);
                break;
            case 9:
                route = route10;
                num_segments = ARRAY_SIZE(route10);
                break;
            case 10:
                route = route11;
                num_segments = ARRAY_SIZE(route11);
                break;
            case 11:
                route = route12;
                num_segments = ARRAY_SIZE(route12);
                break;
            case 12:
                route = route13;
                num_segments = ARRAY_SIZE(route13);
                break;
            case 13:
                route = route14;
                num_segments = ARRAY_SIZE(route14);
                break;
            case 14:
                route = route15;
                num_segments = ARRAY_SIZE(route15);
                break;
            case 15:
                route = route16;
                num_segments = ARRAY_SIZE(route16);
                break;
            case 16:
                route = route17;
                num_segments = ARRAY_SIZE(route17);
                break;
            case 17:
                route = route18;
                num_segments = ARRAY_SIZE(route18);
                break;
            case 18:
                route = route19;
                num_segments = ARRAY_SIZE(route19);
                break;
            case 19:
                route = route20;
                num_segments = ARRAY_SIZE(route20);
                break;
            }

            ship_seconds = seconds;

            // メインループ内で次のゲート名を取得して渡す
            for (int j = 0; j < num_segments; j++)
            {
                Point p;
                double mu = route[j].mean;   // 該当ゲートの平均
                double sigma = route[j].std; // 該当ゲートの標準偏差
                const char *next_gate_name = (j < num_segments - 1) ? route[j + 1].name : "END";

                int use_uniform = 0; // デフォルトは正規分布
                if (route_index == 0 && j == 2)
                { // gateAから出発し、gateCで一様乱数
                    use_uniform = 1;
                }
                else if (route_index >= 12 && route_index <= 15 && j == 1)
                { // gateLから出発するルートで、gateHで一様乱数
                    use_uniform = 1;
                }
                else if (route_index >= 16 && j == 0)
                { // gateEから出発するルートで、最初のセグメント(gateE)で一様乱数
                    use_uniform = 1;
                }
                else if (route_index >= 8 && route_index <= 11 && j == 1)
                { // gateIIから出発し、gateFFで一様乱数
                    use_uniform = 1;
                }
                else if (route_index >= 4 && route_index <= 7 && j == 0)
                { // gateDから出発するルートで、最初のセグメント(gateD)で一様乱数
                    use_uniform = 1;
                }

                generate_random_point(route[j].segment, &p, mu, sigma, use_uniform);

                if (j != 0)
                {
                    if (route[j - 1].speed_mean > 0)
                    {
                        speed = rand_normal(route[j - 1].speed_mean, route[j - 1].speed_std);
                        if (speed < route[j - 1].speed_mean - route[j - 1].speed_std)
                        {
                            speed = route[j - 1].speed_mean - route[j - 1].speed_std;
                        }
                        if (speed > route[j - 1].speed_mean + route[j - 1].speed_std)
                        {
                            speed = route[j - 1].speed_mean + route[j - 1].speed_std;
                        }
                    }
                    record_ship_positions(current_ship_id, last_point, &p, speed, ship_size, ship_seconds, route_colors[route_index], next_gate_name);
                    // 次の船舶のIDを準備

                    ship_seconds += calculate_seconds(last_point, p, speed);
                }
                last_point = p;
            }
        }
        // メインループの冒頭
        int new_record_count = 0;

        fill_empty_records(seconds);

        for (int i = 0; i < record_count; i++)
        {
            if (records[i].seconds == seconds)
            {
                // record_secondsと一致する場合、出力してrecordsには追加しない
                printf("%d\t%.9f\t%.9f\t%.2f\t%.2f\t%.2f\t%d\t%s\n",
                       records[i].seconds - start_seconds, records[i].latitude, records[i].longitude, records[i].heading,
                       records[i].speed, records[i].size, records[i].ship_id, records[i].next_gate_name);
            }
            else
            {
                // 一致しない場合、新しいrecordsに保持
                temp_records[new_record_count++] = records[i];
            }
        }

        // 更新されたカウントを適用
        record_count = new_record_count;

        // 新しいrecordsを古いものと置き換え
        memcpy(records, temp_records, record_count * sizeof(Record));
        seconds += 1;
    }

    return 0;
}