400 lines
12 KiB
C
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(¤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;
|
|
}
|