#include #include #include "csv.h" #include "api.h" #include #include "person.h" #include "vaccine.h" #define FILE_READ_BUFFER_SIZE 2048 #define VACCINE_LOT_TYPE_NAME "VACCINE_LOT" #define VACCINE_LOT_NUM_FIELDS 7 #define MAX_CP_LEN 5 #define MAX_VACCINE_NAME_LEN 15 #define PERSON_TYPE_NAME "PERSON" #define PERSON_NUM_FIELDS 7 #define MAX_PERSON_DOCUMENT_LEN 9 #define MAX_PERSON_NAME_LEN 15 #define MAX_PERSON_EMAIL_LEN 30 #define MAX_PERSON_ADDRESS_LEN 30 #define VACCINE_TYPE_NAME "VACCINE" #define DATE_LEN 10 #define TIME_LEN 5 // Get the API version information const char* api_version() { return "UOC PP 20212"; } // Load data from a CSV file. If reset is true, remove previous data tApiError api_loadData(tApiData* data, const char* filename, bool reset) { tApiError error; FILE *fin; char buffer[FILE_READ_BUFFER_SIZE]; tCSVEntry entry; // Check input data assert( data != NULL ); assert(filename != NULL); // Reset current data if (reset) { // Remove previous information error = api_freeData(data); if (error != E_SUCCESS) { return error; } // Initialize the data error = api_initData(data); if (error != E_SUCCESS) { return error; } } // Open the input file fin = fopen(filename, "r"); if (fin == NULL) { return E_FILE_NOT_FOUND; } // Read file line by line while (fgets(buffer, FILE_READ_BUFFER_SIZE, fin)) { // Remove new line character buffer[strcspn(buffer, "\n\r")] = '\0'; csv_initEntry(&entry); csv_parseEntry(&entry, buffer, NULL); // Add this new entry to the api Data error = api_addDataEntry(data, entry); if (error != E_SUCCESS) { return error; } csv_freeEntry(&entry); } fclose(fin); return E_SUCCESS; } // Initialize the data structure tApiError api_initData(tApiData* data) { ////////////////////////////////// // Ex PR1 2b ///////////////////////////////// population_init(&(data->population)); vaccineList_init(&(data->vaccines)); vaccineLotData_init(&(data->vaccineLots)); return E_SUCCESS; } // Add a new vaccines lot tApiError api_addVaccineLot(tApiData* data, tCSVEntry entry) { ////////////////////////////////// // Ex PR1 2c ///////////////////////////////// tApiError ret = E_NOT_IMPLEMENTED; // Verify num fields and type of entry if (csv_numFields(entry) == VACCINE_LOT_NUM_FIELDS) { if (strcmp(csv_getType(&entry),VACCINE_LOT_TYPE_NAME) == 0) { tVaccine vaccineEntry; tVaccineLot vaccineLotEntry; vaccineLot_parse(&vaccineEntry,&vaccineLotEntry,entry); if (vaccineList_find(data->vaccines,vaccineEntry.name) == NULL) { // Vaccine does not exist in vaccineList // Add vaccine in vaccine list vaccineList_insert(&data->vaccines,vaccineEntry); // Get vaccine item position in vaccine list to be added on vaccineLotData vaccineLotEntry.vaccine = vaccineList_find(data->vaccines,vaccineEntry.name); vaccineLotData_add(&(data->vaccineLots),vaccineLotEntry); } else { // Vaccine already exists in vaccineList // Get vaccine item position in vaccine list to be added on vaccineLotData vaccineLotEntry.vaccine = vaccineList_find(data->vaccines,vaccineEntry.name); vaccineLotData_add(&(data->vaccineLots),vaccineLotEntry); } vaccineLot_free(&vaccineLotEntry); vaccine_free(&vaccineEntry); ret = E_SUCCESS; } else { // numFields other than valid one ret = E_INVALID_ENTRY_TYPE; } } else { // csv record type other than valid one ret = E_INVALID_ENTRY_FORMAT; } return ret; } // Get the number of persons registered on the application int api_populationCount(tApiData data) { ////////////////////////////////// // Ex PR1 2d ///////////////////////////////// return population_len(data.population); } // Get the number of vaccines registered on the application int api_vaccineCount(tApiData data) { ////////////////////////////////// // Ex PR1 2d ///////////////////////////////// return vaccineList_len(data.vaccines); } // Get the number of vaccine lots registered on the application int api_vaccineLotsCount(tApiData data) { ////////////////////////////////// // Ex PR1 2d ///////////////////////////////// return vaccineLotData_len(data.vaccineLots); } // Free all used memory tApiError api_freeData(tApiData* data) { ////////////////////////////////// // Ex PR1 2e ///////////////////////////////// population_free(&(data->population)); vaccineList_free(&(data->vaccines)); vaccineLotData_free(&(data->vaccineLots)); return E_SUCCESS; } // Add a new entry tApiError api_addDataEntry(tApiData* data, tCSVEntry entry) { ////////////////////////////////// // Ex PR1 2f ///////////////////////////////// tApiError ret = E_NOT_IMPLEMENTED; // Check if entry type is Vaccine Lot and its field number is correct if (strcmp(csv_getType(&entry),VACCINE_LOT_TYPE_NAME) == 0) { if (csv_numFields(entry) == VACCINE_LOT_NUM_FIELDS) { ret = api_addVaccineLot(data,entry); } else { // Num fields does not match ret = E_INVALID_ENTRY_FORMAT; } // Check if entry type is Person and its field number is correct } else if (strcmp(csv_getType(&entry),PERSON_TYPE_NAME) == 0) { if (csv_numFields(entry) == PERSON_NUM_FIELDS) { // Process could be implemented in a "api_addPerson()" function // as in "api_addVaccineLot()" tPerson entryPerson; person_init(&entryPerson); person_parse(&entryPerson,entry); // Check if person already exists if (population_find(data->population,entryPerson.document) == -1) { population_add(&(data->population),entryPerson); ret = E_SUCCESS; } else { ret = E_DUPLICATED_PERSON; } person_free(&entryPerson); } else { // Num fields does not match ret = E_INVALID_ENTRY_FORMAT; } } else { ret = E_INVALID_ENTRY_TYPE; } return ret; } // Get vaccine data tApiError api_getVaccine(tApiData data, const char *name, tCSVEntry *entry) { ////////////////////////////////// // Ex PR1 3a ///////////////////////////////// tApiError ret = E_NOT_IMPLEMENTED; tVaccine* found; char buffer[FILE_READ_BUFFER_SIZE]; found = vaccineList_find(data.vaccines,name); if (found) { // If pointer is not null, vaccine exists // Fill buffer with data from the vaccine on that pointer sprintf(buffer, "%s;%d;%d", found->name, found->required, found->days); // Init CSV entry and set values accordingly csv_initEntry(entry); csv_parseEntry(entry,buffer,VACCINE_TYPE_NAME); ret = E_SUCCESS; } else { // If pointer is null, vaccine does not exist ret = E_VACCINE_NOT_FOUND; } return ret; } // Get vaccine lot data tApiError api_getVaccineLot(tApiData data, const char* cp, const char* vaccine, tDateTime timestamp, tCSVEntry *entry) { ////////////////////////////////// // Ex PR1 3b ///////////////////////////////// tApiError ret = E_NOT_IMPLEMENTED; tVaccineLot found; int index; char buffer[FILE_READ_BUFFER_SIZE]; index = vaccineLotData_find(data.vaccineLots,cp,vaccine,timestamp); if (index != -1) { // If value is not -1, vaccineLot exists vaccineLot_cpy(&found,data.vaccineLots.elems[index]); // Fill buffer with data from the vaccineLot sprintf(buffer, "%02d/%02d/%04d;%02d:%02d;%s;%s;%d;%d;%d", found.timestamp.date.day,found.timestamp.date.month,found.timestamp.date.year, found.timestamp.time.hour,found.timestamp.time.minutes, found.cp, found.vaccine->name,found.vaccine->required,found.vaccine->days, found.doses); vaccineLot_free(&found); // Init CSV entry and set values accordingly csv_initEntry(entry); csv_parseEntry(entry,buffer,VACCINE_LOT_TYPE_NAME); ret = E_SUCCESS; } else { // If value is -1, vaccineLot does not exist ret = E_LOT_NOT_FOUND; } return ret; } // Get registered vaccines tApiError api_getVaccines(tApiData data, tCSVData *vaccines) { ////////////////////////////////// // Ex PR1 3c ///////////////////////////////// tApiError ret = E_NOT_IMPLEMENTED; tCSVEntry foundVaccine; tVaccineNode* currentVaccine; char buffer[FILE_READ_BUFFER_SIZE]; char name[MAX_VACCINE_NAME_LEN]; int required; int days; csv_init(vaccines); currentVaccine = data.vaccines.first; // Go through all nodes in vaccine list until current one is nothing while (currentVaccine != NULL) { csv_initEntry(&foundVaccine); // Reuse previous function to get a vaccine by name and have it stored in a CSVEntry if (api_getVaccine(data,currentVaccine->vaccine.name,&foundVaccine) == E_SUCCESS) { // Read vaccine info csv_getAsString(foundVaccine,0,name,MAX_VACCINE_NAME_LEN+1); required = csv_getAsInteger(foundVaccine,1); days = csv_getAsInteger(foundVaccine,2); // Fill new csv string with format required sprintf(buffer,"%s;%d;%d",name,required,days); csv_addStrEntry(vaccines,buffer,VACCINE_TYPE_NAME); ret = E_SUCCESS; } // Clean up dynamic memory used csv_freeEntry(&foundVaccine); // Point currentVaccine to next element to get forward in the loop currentVaccine = currentVaccine->next; } return ret; } // Get vaccine lots tApiError api_getVaccineLots(tApiData data, tCSVData *lots) { ////////////////////////////////// // Ex PR1 3d ///////////////////////////////// tApiError ret = E_NOT_IMPLEMENTED; tCSVEntry foundLot; tVaccineLot currentVaccineLot; char buffer[FILE_READ_BUFFER_SIZE]; tDateTime timestamp; char date[DATE_LEN]; char time[TIME_LEN]; char cp [MAX_CP_LEN]; char vaccine [MAX_VACCINE_NAME_LEN]; int required; int days; int doses; csv_init(lots); for (int i = 0; i < data.vaccineLots.count; i++) { vaccineLot_cpy(¤tVaccineLot,data.vaccineLots.elems[i]); csv_initEntry(&foundLot); if (api_getVaccineLot(data, currentVaccineLot.cp, currentVaccineLot.vaccine->name, currentVaccineLot.timestamp, &foundLot) == E_SUCCESS) { // Fill buffer with data from the vaccinelot sprintf(buffer, "%02d/%02d/%04d;%02d:%02d;%s;%s;%d;%d;%d", currentVaccineLot.timestamp.date.day,currentVaccineLot.timestamp.date.month,currentVaccineLot.timestamp.date.year, currentVaccineLot.timestamp.time.hour,currentVaccineLot.timestamp.time.minutes, currentVaccineLot.cp, currentVaccineLot.vaccine->name,currentVaccineLot.vaccine->required,currentVaccineLot.vaccine->days, currentVaccineLot.doses); csv_addStrEntry(lots,buffer,VACCINE_LOT_TYPE_NAME); vaccineLot_free(¤tVaccineLot); ret = E_SUCCESS; } csv_freeEntry(&foundLot); } return ret; }