#include <iostream>
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
using namespace std;

#define CPU_COUNT 60

//ÇÁ·Î¼¼½º µ¥ÀÌÅ¸ ±¸Á¶Ã¼ »ý¼º.
typedef struct Node {
	char *name;			//ÇÁ·Î¼¼½º ÀÌ¸§
	int base_priority;  //base_priority
	int priority;  //priority
	int time;			//½ÇÇà ½Ã°£
	int K_U;			//Ä¿³Î or »ç¿ëÀÚ ÇÁ·Î¼¼½º
	int CPU_C;
    struct Node *Next;
	char state;
}Node;

typedef Node* Nptr;

class L_List {
public:
	L_List();
	L_List(const L_List &y);
	~L_List();
	void AddTail(Nptr *header, char* _name, int _base_priority, int _time, int _K_U);
	void AddHead(Nptr *header, char* _name, int _base_priority, int _time, int _K_U);
	Nptr Ker_Usr(Nptr header);

	Nptr Check_priority(Nptr &header);
	void Scheduling(Nptr _header, int _V=0);

	void display(Nptr header);
	void Total_Print();
	void ReleaseList();
	Nptr FirstHeader;
	static int END_Process_Count;
	static int Process_Count;
};
int L_List::END_Process_Count=0;
int L_List::Process_Count=0;
//»ý¼ºÀÚ
L_List::L_List() {
	FirstHeader = NULL;
}
//¼Ò¸êÀÚ
L_List::~L_List() {}
//²¿¸®¿¡ Ãß°¡
void L_List::AddTail(Nptr *header, char* _name, int _base_priority, int _time, int _K_U){
    Nptr tail = *header;
    Nptr NewNode = NULL; //»õ ³ëµå ¼±¾ð

    if(*header == NULL)
        AddHead(header, _name, _base_priority, _time, _K_U);
    else{
        // ²¿¸®¸¦ Ã£´Â´Ù.
        while(1){
            if(tail->Next != NULL){
                tail = tail->Next;
                continue;
            }
            break;
        }
		Nptr NewNode = new Node; //»õ ³ëµå µ¿Àû ÇÒ´ç
        tail->Next = NewNode; //²¿¸®¿¡ »õ ³ëµå¸¦ ¿¬°á
        NewNode->Next = NULL; //»õ ³ëµå¸¦ ²¿¸®·Î ¼±¾ð
        NewNode->name = _name; //ÇÁ·Î¼¼½º ÀÌ¸§ ÀÔ·Â
		NewNode->base_priority = _base_priority; //Base priority ÀÔ·Â
		NewNode->time = _time; //½ÇÇà ½Ã°£ ÀÔ·Â
		NewNode->CPU_C=0;
		NewNode->priority=_base_priority;
		NewNode->K_U = _K_U; //Ä¿³Î ¶Ç´Â »ç¿ëÀÚ ÇÁ·Î¼¼½º ÀÔ·Â
		Process_Count++;
		NewNode->state=' ';
    }
}
//¾Õ¿¡´Ù ³Ö±â
void L_List::AddHead(Nptr *header, char* _name, int _base_priority, int _time, int _K_U){
	Nptr NewNode = new Node; //»õ ³ëµå µ¿Àû ÇÒ´ç
    NewNode->name = _name; //ÇÁ·Î¼¼½º ÀÌ¸§ ÀÔ·Â
	NewNode->base_priority = _base_priority; //Base priority ÀÔ·Â
	NewNode->time = _time; //½ÇÇà ½Ã°£ ÀÔ·Â
	NewNode->K_U = _K_U; //Ä¿³Î ¶Ç´Â »ç¿ëÀÚ ÇÁ·Î¼¼½º ÀÔ·Â
    NewNode->Next = *header; //´ÙÀ½ Æ÷ÀÎÅÍ ¼³Á¤
	NewNode->CPU_C=0;
	NewNode->priority=_base_priority;
    *header = NewNode; //Çì´õ¸¦ ±³Ã¼
	FirstHeader=NewNode;
	Process_Count++;
	NewNode->state=' ';
}


//Ãâ·Â¿ë!
void L_List::display(Nptr header) {
    Nptr temp = header;
	cout<<"*:¼öÇàÁßÀÎ ÇÁ·Î¼¼½º #:Á¾·áµÈ ÇÁ·Î¼¼½º"<<endl;
	cout<<"-----------------------------------------------------------------------------"<<endl;
    while(temp != NULL) {
		printf("%5s|%-9s",temp->name, temp->K_U ? "User_P" : "Kern_P");
        temp = temp->Next;
    }
	temp = header;
	cout<<endl;
	while(temp != NULL) {
		printf("%-14s","Pri  CC  rem    ");
        temp = temp->Next;
    }
	cout<<"-----------------------------------------------------------------------------"<<endl;
}

//Á¾·áµÈ ÇÁ·Î¼¼½º¸¦ »èÁ¦ ÇÏ´Â ¸Þ¼Òµå
void L_List::ReleaseList() {
    Nptr temp = FirstHeader;

	while(temp != NULL){
		if(temp->time==0)
			END_Process_Count++;
		temp=temp->Next;
	}
	if (Process_Count==END_Process_Count){
		cout<<"Á¾·áµÇ¾ú½À´Ï´Ù."<<endl;
		cout<<"2002160000 ÀüÈ£Ã¶"<<endl;
		getch();
		cout<<"Á¾·áÇÏ½Ã·Á¸é ¾Æ¹«Å°³ª ´©¸£½Ê½Ã¿ä"<<endl;
		getch();
		exit(0);
	}
	else
		END_Process_Count=0;
}

Nptr L_List::Ker_Usr(Nptr header){
	Nptr Kernel_Min=NULL;
	Nptr now = header;
	bool firstflag=true;
	bool Ufirstflag=true;

	int K_count=0;

	Nptr whiletemp = header;
	while(whiletemp != NULL){  //Ä¿³ÎÀÇ °¹¼ö¸¦ °Ë»çÇÏ¿© ÀúÀå
		if (whiletemp->K_U == 0 && whiletemp->time!=0)
			K_count++;
		whiletemp = whiletemp->Next;
	}

	while(now != NULL){
		if(K_count) {
			if(now->K_U == 0 && now->time != 0){
				if(firstflag){
					firstflag=false;
					Kernel_Min=now;
				}
				else{
					if(Kernel_Min->priority > now->priority)
						Kernel_Min = now;
				}
			}
		}
		if(K_count==0 && now->time != 0) {
			if(now->K_U==1) {
				if(Ufirstflag) {
					Ufirstflag = false;
					Kernel_Min=now;
				} else {
					if(Kernel_Min->priority > now->priority)
						Kernel_Min = now;
				}
			}
		}
		now=now->Next;
	}
	return Kernel_Min;
}

void L_List::Scheduling(Nptr Top_priority, int _V){ //½ºÄÉÁÙ¸µ
	Nptr temp=FirstHeader;

	while(temp != NULL){     //ÀüÃ¼ °Ë»öÇÏ¿©¼­
		if(!strcmp(Top_priority->name, temp->name)){ //¼öÇàµÉ ÇÁ·Î¼¼½º¶ó¸é
			temp->CPU_C=(temp->CPU_C+CPU_COUNT)/2; //CPU COUNT¸¦ ¹ÝÀ¸·Î ³ª´«´Ù.
			temp->priority=temp->base_priority+temp->CPU_C/2+_V;  //¿ì¼±¼øÀ§ Á¶ÀÛ
			temp->time-=1; //³²Àº ½ÇÇà½Ã°£À» °è»êÇÏ¿© ÀúÀå
			temp->state='*';
		}else if(temp->time!=0){  //¼öÇàµÉ Â÷·Ê°¡ ¾Æ´Ï¸é
			temp->CPU_C=temp->CPU_C/2; //CPU COUNT¸¦ ¹ÝÀ¸·Î ³ª´«´Ù.
			temp->priority=temp->base_priority+temp->CPU_C/2; //¿ì¼±¼øÀ§ Á¶ÀÛ
			temp->state=' ';
		}else if(temp->time == 0)
			temp->state='#';
		temp = temp->Next;
	}
	Total_Print();
}

void L_List::Total_Print(){
	Nptr temp=FirstHeader;
	while(temp != NULL){
		printf("%c%4d%4d%4d  ",temp->state,temp->priority, temp->CPU_C, temp->time);
		temp=temp->Next;
		Sleep(50);
	}
	cout<<endl;
}

