2018-06-05 23:15:23 +00:00
//
// Created by Antoine Bartuccio on 05/06/2018.
//
2018-06-06 18:29:02 +00:00
# include <string.h>
2018-06-21 15:39:30 +00:00
# include <math.h>
2018-06-22 01:59:36 +00:00
# include <unistd.h>
2018-06-05 23:15:23 +00:00
# include "Building.h"
2018-06-06 18:29:02 +00:00
# include "../Resident/Resident.h"
# include "../Visitor/Visitor.h"
# define LINE_BUFFER 256
2018-06-06 01:00:35 +00:00
2018-06-21 14:15:33 +00:00
SYNCHRONIZED_GETTER ( Building , int * , waiting_floors )
2018-06-06 18:29:02 +00:00
void remove_end_char ( char * string , char character ) {
size_t string_size = strlen ( string ) ;
if ( string [ string_size - 1 ] = = character )
string [ string_size - 1 ] = ' \0 ' ;
}
2018-06-21 15:39:30 +00:00
/**
* Get the best call for the elevator
* @ param THIS ( Building ) : this
* @ param elevator_floor : actual floor of the requesting elevator
* @ returns the closest floor where a client is calling as an int . If no client is calling , returns - 1.
*/
int get_next_call_Building ( THIS ( Building ) , int elevator_floor ) {
pthread_mutex_lock ( this - > mutex_func_get_next_call ) ;
2018-06-21 14:15:33 +00:00
int * waiting_floors = this - > get_waiting_floors ( this ) ;
2018-06-21 15:39:30 +00:00
int i ;
float best_diff = INFINITY ;
int next_target = - 1 ;
for ( i = 0 ; i < FLOORS ; i + + ) {
if ( waiting_floors [ i ] > 0 ) {
2018-06-21 23:26:00 +00:00
if ( abs ( elevator_floor - i ) < best_diff & & elevator_floor ! = i /*beware*/ ) {
2018-06-21 16:22:02 +00:00
best_diff = abs ( elevator_floor - i ) ;
next_target = i ;
2018-06-21 15:39:30 +00:00
}
}
}
pthread_mutex_unlock ( this - > mutex_func_get_next_call ) ;
return next_target ;
2018-06-21 14:15:33 +00:00
}
2018-06-10 23:58:52 +00:00
List * split ( char * line , char * separator ) {
List * split = NEW ( List ) ;
char * to_delete = strdup ( line ) ;
char * to_delete_back = to_delete ;
2018-06-10 15:57:39 +00:00
char * token = NULL ;
2018-06-10 23:58:52 +00:00
while ( ( token = strsep ( & to_delete , separator ) ) ! = NULL )
split - > insert_tail ( split , ( void * ) token , sizeof ( char ) * strlen ( token ) ) ;
2018-06-10 15:57:39 +00:00
free ( to_delete_back ) ;
2018-06-10 23:58:52 +00:00
return split ;
2018-06-10 15:57:39 +00:00
}
2018-06-06 18:29:02 +00:00
void parse_residents_Building ( THIS ( Building ) , char * file ) {
2018-06-10 15:57:39 +00:00
/* File format is name;appartment_floor;destination */
2018-06-06 18:29:02 +00:00
FILE * f = fopen ( file , " r " ) ;
2018-06-10 23:58:52 +00:00
List * line_split = NULL ;
2018-06-06 18:29:02 +00:00
Resident * resident = NULL ;
size_t len = LINE_BUFFER ;
char * line = NULL ;
char * trash ;
int i = 0 ;
2018-06-15 09:50:38 +00:00
if ( f = = NULL ) {
2018-06-06 18:29:02 +00:00
CRASH ( " File for residents does not exist " ) ;
2018-06-15 09:50:38 +00:00
}
2018-06-06 18:29:02 +00:00
while ( getline ( & line , & len , f ) > 0 ) {
remove_end_char ( line , ' \n ' ) ;
2018-06-10 23:58:52 +00:00
line_split = split ( line , " ; " ) ;
2018-06-06 18:29:02 +00:00
2018-06-10 23:58:52 +00:00
resident = NEW ( Resident , i , line_split - > get_element_data ( line_split , 0 ) ,
( int ) strtol ( line_split - > get_element_data ( line_split , 1 ) , & trash , 10 ) ,
( int ) strtol ( line_split - > get_element_data ( line_split , 2 ) , & trash , 10 ) ) ;
2018-06-06 18:29:02 +00:00
this - > residents - > insert_tail ( this - > residents , resident , sizeof ( Resident ) ) ;
resident - > name = NULL ;
DELETE ( resident ) ;
2018-06-10 23:58:52 +00:00
DELETE ( line_split ) ;
2018-06-06 18:29:02 +00:00
i + + ;
}
free ( line ) ;
fclose ( f ) ;
}
void parse_visitors_Building ( THIS ( Building ) , char * file ) {
2018-06-10 15:57:39 +00:00
/* File format is name;contact_name */
2018-06-06 18:29:02 +00:00
FILE * f = fopen ( file , " r " ) ;
2018-06-10 23:58:52 +00:00
List * line_split = NULL ;
2018-06-06 18:29:02 +00:00
Visitor * visitor = NULL ;
size_t len = LINE_BUFFER ;
char * line = NULL ;
int i = 0 ;
2018-06-15 09:50:38 +00:00
if ( f = = NULL ) {
2018-06-06 18:29:02 +00:00
CRASH ( " File for visitors does not exist " ) ;
2018-06-15 09:50:38 +00:00
}
2018-06-06 18:29:02 +00:00
while ( getline ( & line , & len , f ) > 0 ) {
remove_end_char ( line , ' \n ' ) ;
2018-06-10 15:57:39 +00:00
2018-06-10 23:58:52 +00:00
line_split = split ( line , " ; " ) ;
visitor = NEW ( Visitor , i , line_split - > get_element_data ( line_split , 0 ) ,
line_split - > get_element_data ( line_split , 1 ) ) ;
2018-06-06 18:29:02 +00:00
this - > visitors - > insert_tail ( this - > visitors , visitor , sizeof ( Visitor ) ) ;
2018-06-10 15:57:39 +00:00
visitor - > contact_name = NULL ;
2018-06-06 18:29:02 +00:00
visitor - > name = NULL ;
DELETE ( visitor ) ;
2018-06-10 23:58:52 +00:00
DELETE ( line_split ) ;
2018-06-06 18:29:02 +00:00
i + + ;
}
free ( line ) ;
fclose ( f ) ;
}
void free_resident ( void * data ) {
Resident * r = ( Resident * ) data ;
DELETE ( r ) ;
}
void free_visitor ( void * data ) {
Visitor * v = ( Visitor * ) data ;
DELETE ( v ) ;
}
2018-06-06 01:00:35 +00:00
void _free__Building ( THIS ( Building ) ) {
int i = 0 ;
2018-06-06 18:29:02 +00:00
this - > residents - > clear_custom ( this - > residents , free_resident ) ;
this - > visitors - > clear_custom ( this - > visitors , free_visitor ) ;
2018-06-15 13:38:26 +00:00
pthread_mutex_unlock ( this - > mutex_cond_get_inside_elevator ) ;
pthread_mutex_destroy ( this - > mutex_cond_get_inside_elevator ) ;
pthread_mutex_unlock ( this - > mutex_cond_get_outside_elevator ) ;
pthread_mutex_destroy ( this - > mutex_cond_get_outside_elevator ) ;
pthread_mutex_unlock ( this - > mutex_func_get_inside_elevator ) ;
pthread_mutex_destroy ( this - > mutex_func_get_inside_elevator ) ;
2018-06-10 02:00:01 +00:00
2018-06-21 15:39:30 +00:00
pthread_mutex_unlock ( this - > mutex_func_get_next_call ) ;
pthread_mutex_destroy ( this - > mutex_func_get_next_call ) ;
2018-06-21 14:15:33 +00:00
pthread_mutex_unlock ( & this - > mutex_waiting_floors ) ;
pthread_mutex_destroy ( & this - > mutex_waiting_floors ) ;
2018-06-22 01:59:36 +00:00
pthread_mutex_unlock ( & this - > mutex_repair ) ;
pthread_mutex_destroy ( & this - > mutex_repair ) ;
2018-06-06 01:00:35 +00:00
DELETE ( this - > residents ) ;
2018-06-06 18:29:02 +00:00
DELETE ( this - > visitors ) ;
2018-06-06 01:00:35 +00:00
for ( i = 0 ; i < ELEVATOR_NB ; i + + )
DELETE ( this - > elevators [ i ] ) ;
2018-06-15 17:14:30 +00:00
for ( i = 0 ; i < FLOORS ; i + + ) {
pthread_cond_destroy ( this - > condition_floors [ i ] ) ;
2018-06-10 02:00:01 +00:00
free ( this - > condition_floors [ i ] ) ;
2018-06-15 17:14:30 +00:00
}
2018-06-10 02:00:01 +00:00
free ( this - > condition_floors ) ;
2018-06-15 13:38:26 +00:00
free ( this - > mutex_cond_get_inside_elevator ) ;
free ( this - > mutex_cond_get_outside_elevator ) ;
free ( this - > mutex_func_get_inside_elevator ) ;
2018-06-21 15:39:30 +00:00
free ( this - > mutex_func_get_next_call ) ;
2018-06-06 01:00:35 +00:00
free ( this - > elevators ) ;
free ( this ) ;
}
2018-06-18 21:03:32 +00:00
/**
* Tries to make @ passenger enter an elevator , passenger being at @ current_floor
* @ THIS ( Building )
* @ current_floor the floor where the passenger is trying to enter the elevator
* @ passenger the passenger to put in the elevator
* @ returns an elevator number ( between 0 and ELEVATOR_NB - 1 , inclusive ) , - 1 if no elevator was found ready to accept the passenger
*/
2018-06-20 17:36:00 +00:00
int get_inside_elevator_Building ( THIS ( Building ) , int current_floor , Passenger * passenger ) {
2018-06-10 02:00:01 +00:00
int i ;
/* Make assumption that a waiting elevator is not full */
2018-06-15 13:38:26 +00:00
pthread_mutex_lock ( this - > mutex_func_get_inside_elevator ) ;
2018-06-21 23:50:27 +00:00
printf ( " Passager %s : J'essaye de rentrer dans un ascenseur, à l'étage %d ( id : %d ) \n " , passenger - > get_name ( passenger ) , current_floor , passenger - > get_id ( passenger ) ) ;
2018-06-10 02:00:01 +00:00
for ( i = 0 ; i < ELEVATOR_NB ; i + + ) {
2018-06-15 13:38:26 +00:00
if ( this - > elevators [ i ] - > can_get_inside ( this - > elevators [ i ] , current_floor ) ) {
2018-06-18 21:03:32 +00:00
this - > elevators [ i ] - > add_passenger ( this - > elevators [ i ] , passenger ) ;
2018-06-15 13:38:26 +00:00
pthread_mutex_unlock ( this - > mutex_func_get_inside_elevator ) ;
2018-06-10 02:00:01 +00:00
return i ;
}
}
2018-06-15 13:38:26 +00:00
pthread_mutex_unlock ( this - > mutex_func_get_inside_elevator ) ;
2018-06-10 02:00:01 +00:00
return - 1 ;
}
2018-06-20 17:36:00 +00:00
void go_to_floor_Building ( THIS ( Building ) , int origin , int destination , Passenger * passenger ) {
2018-06-10 02:00:01 +00:00
int elevator_number ;
2018-06-15 09:50:38 +00:00
if ( origin < 0 | | origin > = FLOORS ) { CRASH ( " You are trying to start from a non existing floor \n " ) ; }
2018-06-15 17:14:30 +00:00
if ( destination < 0 | | destination > = FLOORS ) { CRASH ( " You are trying to reach a non existing floor \n " ) ; }
2018-06-10 02:00:01 +00:00
2018-06-21 16:22:02 +00:00
this - > waiting_floors [ origin ] + + ; //on ajoute à la liste des attentes
2018-06-21 22:04:52 +00:00
pthread_mutex_lock ( this - > mutex_cond_get_inside_elevator ) ;
2018-06-15 13:38:26 +00:00
pthread_cond_wait ( this - > condition_floors [ origin ] , this - > mutex_cond_get_inside_elevator ) ;
2018-06-21 22:04:52 +00:00
pthread_mutex_unlock ( this - > mutex_cond_get_inside_elevator ) ;
2018-06-18 21:03:32 +00:00
2018-06-20 20:11:48 +00:00
elevator_number = this - > get_inside_elevator ( this , origin , passenger ) ;
2018-06-18 21:03:32 +00:00
if ( elevator_number ! = - 1 ) { //passenger accepted in elevator
2018-06-21 16:22:02 +00:00
this - > waiting_floors [ origin ] - - ; //on retire de la liste des attentes
2018-06-21 22:48:43 +00:00
pthread_mutex_lock ( this - > mutex_cond_get_outside_elevator ) ;
2018-06-18 21:03:32 +00:00
pthread_cond_wait ( this - > condition_floors [ destination ] , this - > mutex_cond_get_outside_elevator ) ;
2018-06-21 22:48:43 +00:00
pthread_mutex_unlock ( this - > mutex_cond_get_outside_elevator ) ;
2018-06-21 18:26:35 +00:00
this - > elevators [ elevator_number ] - > remove_passenger ( this - > elevators [ elevator_number ] , passenger ) ;
2018-06-18 21:03:32 +00:00
} else {
2018-06-20 17:36:00 +00:00
if ( passenger - > type = = RESIDENT )
2018-06-21 23:50:27 +00:00
printf ( " Résident %s : L'ascenseur à l'étage %d était plein et je n'ai pas pu monter \n " , passenger - > get_name ( passenger ) , origin ) ;
2018-06-20 17:36:00 +00:00
else if ( passenger - > type = = VISITOR )
2018-06-21 23:50:27 +00:00
printf ( " Visiteur %s : L'ascenseur à l'étage %d était plein et je n'ai pas pu monter \n " , passenger - > get_name ( passenger ) , origin ) ;
2018-06-20 20:06:45 +00:00
//reloading fire
2018-06-21 22:04:52 +00:00
this - > waiting_floors [ origin ] - - ;
2018-06-21 19:34:34 +00:00
this - > go_to_floor ( this , origin , destination , passenger ) ;
2018-06-20 15:49:18 +00:00
}
2018-06-18 21:03:32 +00:00
2018-06-10 02:00:01 +00:00
}
2018-06-11 08:52:58 +00:00
int use_call_box_Building ( THIS ( Building ) , char * resident_name ) {
/* Return negative number if not found */
Element * current = this - > residents - > get_head ( this - > residents ) ;
while ( current ! = NULL ) {
if ( ! strcmp ( ( ( Resident * ) current - > get_data ( current ) ) - > name , resident_name ) )
return ( ( Resident * ) current - > get_data ( current ) ) - > apartment_floor ;
current = current - > get_next ( current ) ;
}
return - 1 ;
}
2018-06-15 13:38:26 +00:00
void signal_elevator_at_floor_Building ( THIS ( Building ) , int floor ) {
pthread_cond_signal ( this - > condition_floors [ floor ] ) ;
}
2018-06-22 01:59:36 +00:00
void ask_elevator_reparation_Building ( THIS ( Building ) , Elevator * elevator ) {
printf ( " Technicien : l'ascenseur %s attend pour se faire réparer \n " , elevator - > name ) ;
pthread_mutex_lock ( & this - > mutex_repair ) ;
2018-06-22 03:49:15 +00:00
usleep ( 500000 ) ;
2018-06-22 01:59:36 +00:00
elevator - > repair ( elevator ) ;
pthread_mutex_unlock ( & this - > mutex_repair ) ;
printf ( " Technicien : l'ascenseur %s est maintenant réparé \n " , elevator - > name ) ;
}
2018-06-06 18:29:02 +00:00
Building * _init_Building ( char * residents_file , char * visitors_file ) {
2018-06-06 01:00:35 +00:00
Building * new_building = malloc_or_die ( sizeof ( Building ) ) ;
2018-06-07 20:04:30 +00:00
char elevator_name [ ] = " @ " ;
2018-06-06 01:00:35 +00:00
int i ;
new_building - > floors = FLOORS ;
2018-06-21 14:15:33 +00:00
for ( i = 0 ; i < FLOORS ; i + + )
new_building - > waiting_floors [ i ] = 0 ;
pthread_mutex_init ( & new_building - > mutex_waiting_floors , NULL ) ;
2018-06-22 01:59:36 +00:00
pthread_mutex_init ( & new_building - > mutex_repair , NULL ) ;
2018-06-21 14:15:33 +00:00
2018-06-06 01:00:35 +00:00
new_building - > elevators = malloc_or_die ( sizeof ( Elevator * ) * ELEVATOR_NB ) ;
2018-06-15 13:38:26 +00:00
new_building - > mutex_cond_get_inside_elevator = malloc_or_die ( sizeof ( pthread_mutex_t ) ) ;
new_building - > mutex_cond_get_outside_elevator = malloc_or_die ( sizeof ( pthread_mutex_t ) ) ;
new_building - > mutex_func_get_inside_elevator = malloc_or_die ( sizeof ( pthread_mutex_t ) ) ;
2018-06-21 15:39:30 +00:00
new_building - > mutex_func_get_next_call = malloc_or_die ( sizeof ( pthread_mutex_t ) ) ;
2018-06-15 13:38:26 +00:00
pthread_mutex_init ( new_building - > mutex_cond_get_inside_elevator , NULL ) ;
pthread_mutex_init ( new_building - > mutex_cond_get_outside_elevator , NULL ) ;
pthread_mutex_init ( new_building - > mutex_func_get_inside_elevator , NULL ) ;
2018-06-21 15:39:30 +00:00
pthread_mutex_init ( new_building - > mutex_func_get_next_call , NULL ) ;
2018-06-15 13:38:26 +00:00
2018-06-10 02:00:01 +00:00
new_building - > condition_floors = malloc_or_die ( sizeof ( pthread_cond_t * ) * FLOORS ) ;
2018-06-06 01:00:35 +00:00
new_building - > residents = NEW ( List ) ;
2018-06-06 18:29:02 +00:00
new_building - > visitors = NEW ( List ) ;
2018-06-07 20:04:30 +00:00
for ( i = 0 ; i < ELEVATOR_NB ; i + + ) {
elevator_name [ 0 ] + + ;
new_building - > elevators [ i ] = NEW ( Elevator , elevator_name ) ;
}
2018-06-10 02:00:01 +00:00
for ( i = 0 ; i < FLOORS ; i + + ) {
new_building - > condition_floors [ i ] = malloc_or_die ( ( sizeof ( pthread_cond_t ) ) ) ;
pthread_cond_init ( new_building - > condition_floors [ i ] , NULL ) ;
}
2018-06-06 01:00:35 +00:00
2018-06-06 18:29:02 +00:00
2018-06-06 01:00:35 +00:00
LINK_ALL ( Building , new_building ,
2018-06-22 01:59:36 +00:00
parse_residents ,
parse_visitors ,
get_inside_elevator ,
use_call_box ,
go_to_floor ,
get_next_call ,
get_waiting_floors ,
signal_elevator_at_floor ,
ask_elevator_reparation
2018-06-06 01:00:35 +00:00
)
2018-06-06 18:29:02 +00:00
if ( residents_file ! = NULL )
new_building - > parse_residents ( new_building , residents_file ) ;
if ( visitors_file ! = NULL )
new_building - > parse_visitors ( new_building , visitors_file ) ;
2018-06-06 01:00:35 +00:00
return new_building ;
2018-06-18 21:03:32 +00:00
}