#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "lcgrand.h"
#define Q_LIMIT_i 100
#define Q_LIMIT_r 100
#define BUSY 1
#define IDLE 0
#define arrival_i1 0
#define arrival_i2 1
#define arrival_r 2
#define departure_i1 3
#define departure_r1 4
#define departure_r2 5
#define termination 6
typedef struct event{
float time;
int event_type;
struct event *next;
} *EVENT;
EVENT event;//事件
int server_status_i1, server_status_r1,server_status_r2;//server 狀態 busy或idle
int num_in_qi, num_in_qr; //inspection & repair 已使用queue數目
int event_type; //系統當前資料型態
int count; //計數器,計算多少人次成功從inspection離開
float time_arrival_i[Q_LIMIT_i], time_arrival_r[Q_LIMIT_r];//inspection & repair的queue
float sim_time;//使用者想模擬多久
float present_time;//系統當前時間
float cumulative_using_i1, cumulative_using_r1, cumulative_using_r2;//累計使用inspection & repair 各個server的時間
float last_BUSY_start_i1, last_BUSY_start_r1, last_BUSY_start_r2;// 最近一次 inspection & repair 各個server 是開始busy的時刻
int Max_capacity_i;//inspection 最大服務數目;
int initialize(float);//初始化(預計模擬的時間)
int timing(EVENT); //更新現在時間,系統最新狀態(事件list)
int arrive_i(float,int);//inspection到達事件發生時,系統inspection要進行的事,包含立即處理並產生離開事件,新到達事件or加入queue(事件發生時間,事件來源)
int arrive_r(float);//repair到達事件發生時,系統inspection要進行的事,包含立即處理並產生離開事件or加入queue(事件發生時間,事件來源)
int depart_i(float);//inspection離開事件發生時,系統inspection要進行的事,包含從queue讀取新資料並機率產生離開事件or改成idle(事件發生時間)
int depart_r(float,int);//repair離開事件發生時,系統repair要進行的事,包含從queue讀取新資料並機率產生離開事件,or改成idle(事件發生時間,事件來源)
int report(FILE *);//資料統計
int generate_event(int,float);//產生事件並加入事件串列中(事件資料型態,事件發生時間)
int add_in_q(float[],float,int*); //將資料加入queue中(目標queue,要傳進去的資料,已使用queue的數目)
float read_from_q(float[],int*);//從queue中讀取一筆資料(目標queue,已使用queue的數目)
float uniform(float,float);
float expon(float);
int main(){
FILE *outfile;
outfile = fopen("d:\\example file\\bus_maintenance_depot.dat", "a");
printf("Input the desired simulation time:\n");
scanf("%f",&sim_time);
initialize(sim_time);
timing(event);
while(event_type != termination){
switch(event_type){
case 0:
case 1:
arrive_i(present_time,event_type);
break;
case 2:
arrive_r(present_time);
break;
case 3:
depart_i(present_time);
break;
case 4:
case 5:
depart_r(present_time,event_type);
break;
}
timing(event);
}
report(outfile);
fclose(outfile);
system("PAUSE");
return 0;
}
int initialize(float simulation_time){
present_time = 0;
event = NULL;
server_status_i1 = IDLE; server_status_r1 = IDLE; server_status_r2 = IDLE;
num_in_qi = 0; num_in_qr = 0;
event_type = 7;
generate_event(arrival_i1, present_time + expon(2));
generate_event(termination, simulation_time);
count = 0;
cumulative_using_i1 = 0; cumulative_using_r1 = 0; cumulative_using_r2 = 0;
last_BUSY_start_i1 = 0; last_BUSY_start_r1 = 0; last_BUSY_start_r2 = 0;
Max_capacity_i = 1;
return 0;
}
int timing(EVENT event_recieved){
present_time = event_recieved->time;
event_type = event_recieved->event_type;
EVENT temp = NULL;
temp = event_recieved;
event_recieved = event_recieved->next;
free(temp);
return 0;
}
int arrive_i(float time_arrival,int event_type_a){
if(server_status_i1 == IDLE){
server_status_i1 = BUSY;
last_BUSY_start_i1 = present_time;
generate_event(departure_i1, present_time + uniform(0.25,1.05));
if(event_type_a == arrival_i1)
generate_event(arrival_i1, present_time + expon(2));
}
else{
if(num_in_qi < Q_LIMIT_i){
add_in_q(time_arrival_i, time_arrival, &num_in_qi);
if(event_type_a == arrival_i1)
generate_event(arrival_i1, present_time + expon(2));
Max_capacity_i = (num_in_qi + 1 > Max_capacity_i)? (num_in_qi + 1) : Max_capacity_i;
}
else{
printf("Queue of inspection shop is empty, so stop simulation clock");
generate_event(termination, present_time);
}
}
return 0;
}
int arrive_r(float time_arrival){
if(server_status_r1 == IDLE){
server_status_r1 = BUSY;
last_BUSY_start_r1 = present_time;
generate_event(departure_r1, present_time + uniform(2.1,4.5));
}
else if(server_status_r2 == IDLE){
server_status_r2 = BUSY;
last_BUSY_start_r2 = present_time;
generate_event(departure_r2, present_time + uniform(2.1,4.5));
}
else{
if(num_in_qr < Q_LIMIT_r)
add_in_q(time_arrival_r, time_arrival, &num_in_qr);
else{
printf("Queue of repair shop is empty, so stop simulation clock");
generate_event(termination, present_time);
}
}
return 0;
}
int depart_i(float time_departure){
if(uniform(0,1) <= 0.3)
generate_event(arrival_r, present_time);
else
count++;
if(num_in_qi == 0){
cumulative_using_i1 = present_time - last_BUSY_start_i1;
server_status_i1 = IDLE;
}
else{
read_from_q(time_arrival_i, &num_in_qi);
generate_event(departure_i1, present_time + uniform(0.25,1.05));
}
return 0;
}
int depart_r(float time_departure,int event_type_d){
if(uniform(0,1) <= 0.5)
generate_event(arrival_i2, present_time);
if(num_in_qr == 0){
switch(event_type_d){
case 4:
cumulative_using_r1 = present_time - last_BUSY_start_r1;
server_status_r1 = IDLE;
break;
case 5:
cumulative_using_r2 = present_time - last_BUSY_start_r2;
server_status_r2 = IDLE;
break;
}
}
else{
read_from_q(time_arrival_r, &num_in_qr);
switch(event_type_d){
case 4:
generate_event(departure_r1, present_time + uniform(2.1,4.5));
break;
case 5:
generate_event(departure_r2, present_time + uniform(2.1,4.5));
break;
}
}
return 0;
}
int report(FILE *o_file){
static float utilization_i1, utilization_r1, utilization_r2;
fprintf(o_file, "average no. successful passing inspection per hr = %f\n", count/present_time);
if(server_status_i1 == BUSY)
utilization_i1 = (cumulative_using_i1 + present_time - last_BUSY_start_i1)/present_time;
else
utilization_i1 = cumulative_using_i1/present_time;
if(server_status_r1 == BUSY)
utilization_r1 = (cumulative_using_r1 + present_time - last_BUSY_start_r1)/present_time;
else
utilization_r1 = cumulative_using_r1/present_time;
if(server_status_r2 == BUSY)
utilization_r2 = (cumulative_using_r2 + present_time - last_BUSY_start_r2)/present_time;
else
utilization_r2 = cumulative_using_r2/present_time;
fprintf(o_file, "utilzation\n");
fprintf(o_file, "inspecton_server_1 repair_server_1 repair_server_2\n");
fprintf(o_file, "%15.4f %15.4f %15.4f",utilization_i1,utilization_r1,utilization_r2);
fprintf(o_file, "maximum capcity of inspection depot with p = 0.5 is %d\n", Max_capacity_i);
return 0;
}
int generate_event(int next_event_type,float next_event_time){
EVENT ptr = (EVENT)malloc(sizeof(struct event));
ptr->event_type = next_event_type;
ptr->time = next_event_time;
ptr->next = NULL;
if(event == NULL)
event = ptr;
else if(ptr->time <= event->time){
ptr->next = event;
event = ptr;
}
else{
EVENT current = event;
EVENT prev = NULL;
while(current != NULL && ptr->time > current->time){
prev = current;
current = current->next;
}
prev->next = ptr;
ptr->next = current;
}
return 0;
}
int add_in_q(float data[],float data_arrival,int *num_in_qu){
data[*num_in_qu] = data_arrival;
(*num_in_qu)++;
return 0;
}
float read_from_q(float data[],int *num_in_qu){
(*num_in_qu)--;
static float temp;
temp = data[0];
int i;
for(i=0; i< *num_in_qu - 1; i++)
data[i] = data[i+1];
return temp;
}
float uniform(float lower,float upper){
return lower + lcgrand(1)*(upper - lower);
}
float expon(float mean){
return -mean*log(lcgrand(1));
}