import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
 * 进程管理对象的实现类
 */
public class FCFS {

    /**使用链表存储进程对象,进程队列*/
    private static List<Job> jobList=new ArrayList<Job>();
    /**系统处理进程的总耗时*/
    private static float time;
    /**平均周转时间*/
    private static float avTurnTime;
    /**平均等待时间*/
    private static float avWaitTime;
    /**平均带权周转时间*/
    private static float avWeightTime;

    //主函数
    public static void main(String[] args) {
        initialList();
        input();
        List<Job> list=FSFC();
        //输出进程信息。
        for(Job job:list){
            System.out.println("进程名:"+job.getJobName()+
                            ",到达时间:"+job.getReachTime()+
                            ",运行时间:"+job.getServeTime()+
                            ",开始执行时间:" + job.getStartTime()+
                            ",完成时间:"+job.getRunTime()+
                            ",周转时间:"+job.getTurnTime()+
                            ",带权周转时时间:"+job.getAvTuTime()+
                            ",等待时间:"+job.getWaitTime());
        }
        calculateTheAverage(list);
        System.out.println("处理总时间为:"+time+
                            ",平均周转时间: "+avTurnTime+
                            ",平均带权周转时间:"+avWeightTime+
                            ",平均等待时间: "+avWaitTime);
    }
    /**
     * 初始化链表
     */
    public static void initialList(){
        System.out.println("请输入要处理的作业数");
        Scanner in=new Scanner(System.in);
        int length=in.nextInt();
        for (int i = 0; i < length; i++) {
            jobList.add(new Job());
        }
    }

    /**
     * 输入作业名和到达时间和服务时间
     */
    public static void input() {
        for (int i = 0; i < jobList.size(); i++) {
            Job job=jobList.get(i);
            System.out.println("请输入第"+(i+1)+"个作业名");
            Scanner in=new Scanner(System.in);
            job.setJobName(in.next());
            System.out.println("请输入第"+(i+1)+"个作业的到达时间");
            job.setReachTime(in.nextFloat());
            System.out.println("请输入第"+(i+1)+"个作业的服务时间");
            job.setServeTime(in.nextFloat());
        }
    }
    /**
     * 发现集合中的最小值,并返回其对应的下标
     * @return
     */
    public static int findMin(){
        //获得第一个进程的到达时间
        float min=jobList.get(0).getReachTime();
        for (int i = 0; i < jobList.size(); i++) {
            if(min>jobList.get(i).getReachTime()){
                min=jobList.get(i).getReachTime();
            }
        }
        for (int i = 0; i < jobList.size(); i++) {
            if(min==jobList.get(i).getReachTime()){
                return i;
            }
        }
        return -1;
    }

    /**
     * 作业处理
     * @return
     */
    public static List<Job> FSFC(){

        List<Job> resultQueue=new ArrayList<>();//完成队列
        int index=0;

        while(jobList.size()!=0){
            //发现集合中的进程到达时间最小的下标
            index=findMin();

            //判断进程处理总时间是否为空,为空说明PCB刚刚开始
            //获得对应下标的对象
            Job job=jobList.get(index);

            //系统开始位第一个进程服务
            if(time==0){
                //第一个进程,开始执行时间=进程到达时间

                //计算开始执行时间
                job.setStartTime(job.getReachTime());

                //完成时间=开始执行时间+服务时间
                job.setRunTime(job.getStartTime()+job.getServeTime());

                //周转时间=完成时间-到达时间
                job.setTurnTime(job.getRunTime()-job.getReachTime());

                //带权周转时间=周转时间/运行时间(服务时间)
                job.setAvTuTime((job.getTurnTime()/job.getServeTime()));

                //等待时间=周转时间-运行时间
                job.setWaitTime(job.getTurnTime()-job.getServeTime());

                //此时系统时间=该进程的完成时间
                time=job.getRunTime();
            }else {
                //如果前一个完成时间,小于到达时间,系统有空闲
                if(time<job.getReachTime()){

                    //空闲出来的时间
                    float idle=job.getReachTime()-time;

                    time+=idle;
                }
                //排除第一个进程 开始执行时间=系统时间
                job.setStartTime(time);
                //完成时间=开始执行时间+服务时间(运行时间)
                job.setRunTime(job.getStartTime()+job.getServeTime());
                //周转时间=完成时间-到达时间
                job.setTurnTime(job.getRunTime()-job.getReachTime());
                //带权周转时间=周转时间/运行时间(服务时间)
                job.setAvTuTime(job.getTurnTime()/ job.getServeTime());
                //等待时间=周转时间-运行时间
                job.setWaitTime(job.getTurnTime()-job.getServeTime());
                //修正系统时间 此时系统时间=原来系统时间+此进程的完成时间(服务时间)
                time+=job.getServeTime();
            }
            //将处理完成的进程添加到完成队列中
            resultQueue.add(job);
            //将此进程移除原先队列
            jobList.remove(index);
        }
        return resultQueue;
    }
    /**
     * 根据传入的集合
     * 计算平均周转时间、平均带权周转时间、平均等待时间
     */
    public static void calculateTheAverage(List<Job> jobList ){
        //总周转时间
        float turnAroundTime=0;
        //总带权周转时间
        float weighTurnAroundTime=0;
        //总等待时间
        float waitingTime=0;
        for(Job job:jobList){
            turnAroundTime+=job.getTurnTime();
            weighTurnAroundTime+=job.getAvTuTime();
            waitingTime+=job.getWaitTime();
        }
        //计算平均值
        avTurnTime=turnAroundTime/jobList.size();
        avWaitTime=waitingTime/jobList.size();
        avWeightTime=weighTurnAroundTime/jobList.size();
    }
}