1
Fork 0
This repository has been archived on 2022-04-02. You can view files and clone it, but cannot push or open issues or pull requests.
UOC_PP20212_PR/UOC20212/UOCVaccine/src/api.c
2022-04-02 16:13:51 +02:00

400 lines
12 KiB
C

#include <stdio.h>
#include <assert.h>
#include "csv.h"
#include "api.h"
#include <string.h>
#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(&currentVaccineLot,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(&currentVaccineLot);
ret = E_SUCCESS;
}
csv_freeEntry(&foundLot);
}
return ret;
}