#include <stdio.h>

#define MAX_PROCESS 5
#define TIME_SLICE 1//时间片大小（单位时间）
// 进程状态
typedef enum {
    RUNNING = 1,
    READY = 0,
    FINISHED = -1
} State;

// 进程控制块结构体
typedef struct {
    int pid;            // 进程ID
    int priority;       // 优先级
    int need_time;      // 需要的运行时间
    int arrival_time;   // 到达时间
    int start_time;     // 开始时间
    int finish_time;    // 完成时间
    State state;        // 状态
} PCB;

// 全局变量
PCB processes[MAX_PROCESS];
int current_time = 0;

// 初始化进程数据
void init_processes() {
    // 数据格式：{pid, priority, need_time, arrival_time, start_time, finish_time, state}
    // 修正后：每个进程只保留7个数据
    processes[0] = (PCB){1, 2, 3, 4, -1, 0, READY};
    processes[1] = (PCB){2, 5, 2, 2, -1, 0, READY};
    processes[2] = (PCB){3, 1, 4, 1, -1, 0, READY};
    processes[3] = (PCB){4, 3, 3, 3, -1, 0, READY};
    processes[4] = (PCB){5, 4, 1, 0, -1, 0, READY};
}

// 检查是否所有进程都已完成
int all_finished() {
    for (int i = 0; i < MAX_PROCESS; i++) {
        if (processes[i].state != FINISHED) {
            return 0; // 还有未完成的
        }
    }
    return 1; // 全部完成
}

// 选择优先级最高的进程
int select_highest_priority() {
    int selected = -1;
    int max_priority = -1;

    for (int i = 0; i < MAX_PROCESS; i++) {
        // 检查进程是否已到达且处于就绪状态
        if (processes[i].state == READY && processes[i].arrival_time <= current_time) {
            if (processes[i].priority > max_priority) {
                max_priority = processes[i].priority;
                selected = i;
            }
            // 优先级相同时，比较 PID (或其他规则，这里保持原代码逻辑)
            else if (processes[i].priority == max_priority) {
                if (selected != -1 && processes[i].pid < processes[selected].pid) {
                    selected = i;
                }
            }
        }
    }
    return selected;
}

int main() {
    init_processes();

    printf("---进程调度模拟过程---\n");
    printf("调度算法: 最高优先树优先(抢占式,动态优先级)\n");
    printf("动态规则: 每获得一次CPU,优先数减1\n\n");

    int last_selected = -1;

    // 主调度循环
    while (!all_finished()) {
        int selected = select_highest_priority();

        // 如果没有进程可运行（可能是还没到达），时间前移
        if (selected == -1) {
            current_time++;
            last_selected = -1; // 重置上一次选择
            continue;
        }

        // 记录开始时间
        if (processes[selected].start_time == -1) {
            processes[selected].start_time = current_time;
        }

        // 进程切换提示
        if (last_selected != selected) {
            printf("->时刻%d: 选中进程P%d (优先级=%d, 剩余时间=%d)\n",
                   current_time, processes[selected].pid, processes[selected].priority, processes[selected].need_time);
        }

        // 执行进程 (运行一个时间单位)
        processes[selected].state = RUNNING;
        processes[selected].need_time--;
        current_time++;

        // 动态优先级调整：运行一次后优先级减1
        if (processes[selected].priority > 0) {
            processes[selected].priority--;
        }

        // 检查进程是否完成
        if (processes[selected].need_time == 0) {
            processes[selected].state = FINISHED;
            processes[selected].finish_time = current_time;
            printf("进程P%d已完成! (完成时刻=%d)\n", processes[selected].pid, current_time);
        } else {
            // 未完成则变回就绪状态
            processes[selected].state = READY;
        }

        last_selected = selected;
    }

    // 统计与输出结果
    printf("\n---调度完成---\n");
    printf("进程\t到达时间\t开始时间\t总运行时间\t完成时间\t周转时间\n");

    int total_turnaround = 0;
    for (int i = 0; i < MAX_PROCESS; i++) {
        // 计算周转时间 = 完成时间 - 到达时间
        int turnaround = processes[i].finish_time - processes[i].arrival_time;
        total_turnaround += turnaround;

        // 原始总运行时间 = 需要时间 + (初始需要时间 - 剩余时间，这里简单用初始need_time推算)
        // 注意：因为 need_time 在循环中被减为 0 了，这里为了演示，假设初始 need_time 已知或需额外字段存储
        // 在本代码中，由于初始化数据是一样的，且被修改了，这里打印 finish - start 近似作为运行时间展示
        int run_time = processes[i].finish_time - processes[i].start_time;

        printf("P%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n",
               processes[i].pid,
               processes[i].arrival_time,
               processes[i].start_time,
               run_time,
               processes[i].finish_time,
               turnaround);
    }

    printf("\n平均周转时间: %.2f\n", (float)total_turnaround / MAX_PROCESS);

    return 0;
}