/*****************************************************************************
PRAC3
******************************************************************************/
/****************************************************************************
Includes
******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "marnet.h"
/******************************************************************************
Funcions bàsiques
******************************************************************************/
void init_date (tDate *d)
{
d->minutes =0;
d->hour = 0;
d->day = 0;
d->month = 0;
d->year = 0;
}
void get_current_date(tDate *d)
{
time_t now;
struct tm *tm;
d->year = tm->tm_year+1900;
d->month = tm->tm_mon+1;
d->day = tm->tm_mday;
d->hour = tm->tm_hour+1;
d->minutes = tm->tm_min+1;
}
/*****
Funcions bàsiques tSupplier
******/
tSupplier newSupplier()
{
int i;
tSupplier sup;
sup.idSupplier = 0;
sup.name[0] = '\0';
sup.addr[0] = '\0';
for( i = 0; i < MAX_PHONE; i++ )
sup.phone[i] = 0;
sup.firstFur = NULL;
sup.currFur = NULL;
sup.profitMargin = 0.0;
return sup;
}
int sup_get_id( tSupplier s )
{
return s.idSupplier;
}
void sup_set_id( tSupplier *s, int i )
{
s->idSupplier = i;
}
void sup_get_name( tSupplier s, tString *st )
{
}
void sup_set_name( tSupplier *s, tString n )
{
}
void sup_get_addr( tSupplier s, tString *st )
{
}
void sup_set_add( tSupplier *s, tString n )
{
}
void sup_get_phone( tSupplier s, int phone[MAX_PHONE] )
{
int i;
for( i = 0; i < MAX_PHONE; i++ )
phone[i] = s.phone[i];
}
void sup_set_phone( tSupplier *s, int phone[MAX_PHONE] )
{
int i;
for( i = 0; i < MAX_PHONE; i++ )
s->phone[i] = phone[i];
}
/*****
Funcions bàsiques tFurniture
*****/
tFurniture newFurniture()
{
int i;
tFurniture fur;
fur.idFurniture = 0;
fur.idSup = 0;
fur.nameFur[0] = '\0';
for( i = 0; i < MAX_SIZES; i++ )
fur.sizes[i] = 0.0;
fur.typeFur[0] = '\0';
fur.color = white;
fur.costPrice = 0.0;
fur.retailPrice = 0.0;
fur.deliveryTime = 0;
fur.prevFur = NULL;
fur.nextFur = NULL;
fur.prevFurType = NULL;
fur.nextFurType = NULL;
return fur;
}
int fur_get_id( tFurniture f )
{
return f.idFurniture;
}
void fur_set_id( tFurniture *f, int i )
{
f->idFurniture = i;
}
int fur_get_idSupplier( tFurniture f )
{
return f.idSup;
}
void fur_set_idSupplier( tFurniture *f, int i )
{
f->idSup = i;
}
void fur_get_name( tFurniture f, tString *st )
{
}
void fur_set_name( tFurniture *f, tString n )
{
}
void fur_get_sizes( tFurniture f, float r[MAX_SIZES] )
{
int i;
for( i = 0; i < MAX_SIZES; i++ )
r[i] = f.sizes[i];
}
void fur_set_sizes( tFurniture *f, float r[MAX_SIZES] )
{
int i;
for( i = 0; i < MAX_SIZES; i++ )
f->sizes[i] = r[i];
}
void fur_get_type( tFurniture f, tString *st )
{
}
void fur_set_type( tFurniture *f, tString n )
{
}
tColor fur_get_color( tFurniture f )
{
return f.color;
}
void fur_set_color( tFurniture *f, tColor c )
{
f->color = c;
}
float fur_get_costPrice( tFurniture f )
{
return f.costPrice;
}
void fur_set_costPrice( tFurniture *f, float r )
{
f->costPrice = r;
}
float fur_get_retailPrice( tFurniture f )
{
return f.retailPrice;
}
void fur_set_retailPrice( tFurniture *f, float r )
{
f->retailPrice = r;
}
int fur_get_deliveryTime( tFurniture f )
{
return f.deliveryTime;
}
void fur_set_deliveryTime( tFurniture *f, int i )
{
f->deliveryTime = i;
}
/*****
Funcions bàsiques tCustomerOrder
*****/
tCustomerOrder newCustOrder()
{
int i;
tCustomerOrder co;
co.idOrder = 0;
co.nameCust[0] = '\0';
co.addrCust[0] = '\0';
for( i = 0; i < MAX_PHONE; i++ )
co.phoneCust[i] = 0;
init_date(&co.createdDate);
co.state = cPending;
co.firstItem = NULL;
co.currItem = NULL;
co. nextCustOrder = NULL;
return co;
}
int custOrd_get_id( tCustomerOrder co )
{
return co.idOrder;
}
void custOrd_set_id( tCustomerOrder *co, int i )
{
co->idOrder = i;
}
void custOrd_get_name( tCustomerOrder co, tString *st )
{
}
void custOrd_set_name( tCustomerOrder *co, tString n )
{
}
void custOrd_get_addr( tCustomerOrder co, tString *st )
{
}
void custOrd_set_addr( tCustomerOrder *co, tString n )
{
}
void custOrd_get_phone( tCustomerOrder co, int phone[MAX_PHONE] )
{
int i;
for( i = 0; i < MAX_PHONE; i++ )
phone[i] = co.phoneCust[i];
}
void custOrd_set_phone( tCustomerOrder *co, int phone[MAX_PHONE] )
{
int i;
for( i = 0; i < MAX_PHONE; i++ )
co->phoneCust[i] = phone[i];
}
tDate custOrd_get_createdDate( tCustomerOrder co )
{
return co.createdDate;
}
void custOrd_set_createdDate( tCustomerOrder *co, tDate td )
{
co->createdDate = td;
}
tCustState custOrd_get_state( tCustomerOrder co )
{
return co.state;
}
void custOrd_set_state( tCustomerOrder *co, tCustState st )
{
co->state = st;
}
/*****
Funcions bàsiques tOrderRow
*****/
int orderRow_get_idProv( tOrderRow o )
{
return o.idProv;
}
void orderRow_set_idProv( tOrderRow *o, int i )
{
o->idProv = i;
}
int orderRow_get_idFur( tOrderRow o )
{
return o.idFur;
}
void orderRow_set_idFur( tOrderRow *o, int i )
{
o->idFur = i;
}
int orderRow_get_unit( tOrderRow o )
{
return o.unit;
}
void orderRow_set_unit( tOrderRow *o, int i )
{
o->unit = i;
}
float orderRow_get_unitCostPrice( tOrderRow o )
{
return o.unitCostPrice;
}
void orderRow_set_unitCostPrice( tOrderRow *o, float i )
{
o->unitCostPrice = i;
}
float orderRow_get_profitMargin( tOrderRow o )
{
return o.profitMargin;
}
void orderRow_set_profitMargin( tOrderRow *o, float i )
{
o->profitMargin = i;
}
/*****
Funcions bàsiques tSupplierOrder
*****/
tSupplierOrder *newSupplierOrder()
{
int i;
tSupplierOrder *supOrd;
supOrd
= malloc(sizeof(tSupplierOrder
));
supOrd->idOrder = 0;
supOrd->idSupplier = 0;
init_date(&supOrd->createdDate);
init_date(&supOrd->receivedDate);
supOrd->state = sPending;
supOrd->firstItem = NULL;
supOrd->currItem = NULL;
supOrd->totalPrice = 0;
supOrd->nextSupOrder = NULL;
return supOrd;
}
int supOrd_get_id( tSupplierOrder so )
{
return so.idOrder;
}
void supOrd_set_id( tSupplierOrder *so, int i )
{
so->idOrder = i;
}
int supOrd_get_idSupplier( tSupplierOrder so )
{
return so.idSupplier;
}
void supOrd_set_idSupplier( tSupplierOrder *so, int i )
{
so->idSupplier = i;
}
tDate supOrd_get_createdDate( tSupplierOrder so )
{
return so.createdDate;
}
void supOrd_set_createdDate( tSupplierOrder *so, tDate td )
{
so->createdDate = td;
}
tDate supOrd_get_receivedDate( tSupplierOrder so )
{
return so.receivedDate;
}
void supOrd_set_receivedDate( tSupplierOrder *so, tDate td )
{
so->receivedDate = td;
}
tSupState supOrd_get_state( tSupplierOrder so )
{
return so.state;
}
void supOrd_set_state( tSupplierOrder *so, tSupState st )
{
so->state = st;
}
float supOrd_get_totalPrice( tSupplierOrder so )
{
return so.totalPrice;
}
void supOrd_set_totalPrice( tSupplierOrder *so, float r )
{
so->totalPrice = r;
}
/*****
Funcions basiques: Esborrar moble del cataleg d'un proveidor
*****/
void sup_del_furniture (tSupplier *s, tFurniture f)
{
// recuperem la llista de tFurniture's del supplier
tFurniture *current;
// Busquem el moble a esborrar
current = s->firstFur;
while( (current != NULL) && (current->idFurniture != f.idFurniture))
{
current = current->nextFur;
}
// Si hem trobat el moble: actualitzem apuntadors de les llistes doblement encadenades a les queal pentany
if( current->idFurniture == f.idFurniture )
{
// Llista de mobles de tSupplier
// Actualitzem apuntador seguent de prevFur a l'element seguent al que estem esborrant
if( current->prevFur )
{
current->prevFur->nextFur = current->nextFur;
}
// Actualitzem apuntador anterior de nextFur a l'element anterio al que estem esborrant
if( current->nextFur )
{
current->nextFur->prevFur = current->prevFur;
}
// Llista de mobles de tType
// Actualitzem apuntador seguent de prevFurType a l'element seguent al que estem esborrant
if( current->prevFurType )
{
current->prevFurType->nextFurType = current->nextFurType;
}
// Actualitzem apuntador anterior de nextFurType a l'element anterio al que estem esborrant
if( current->nextFurType )
{
current->nextFurType->prevFurType = current->prevFurType;
}
}
}
/*****
Funcions basiques: Crear/Consultar/Modificar el percentatge de beneficis a un preu de cost
*****/
float sup_get_profitMargin (tSupplier s)
{
return s.profitMargin;
}
void sup_set_profitMargin (tSupplier *s, float r)
{
tFurniture *furAux;
s->profitMargin = r;
// Hem de recorrer tot el cataleg de mobles per actualitzar el PVP amb el nou percentatge de beneficis
furAux = s->firstFur;
while(furAux != NULL)
{
furAux->retailPrice = furAux->costPrice + (furAux->costPrice * r / 100);
furAux = furAux->nextFur;
}
}
/*****
Funcions basiques: Crear comanda a proveïdors a partir de la comanda del client
*****/
// Afegim funcio auxiliar getNewSupIdOrder que ens retorna un nou id de comanda proveidors
int getNewSupIdOrder(int idCustOrder, int idSupplier)
{
tString aux;
int newID;
// Per crear un nou idSupplier per a la comanda a proveidors concatenem id comanda client amb id proveidor
sprintf(aux
, "%d%d", idCustOrder
, idSupplier
);
return newID;
}
tSupplierOrder *supOrder_create(tCustomerOrder co)
{
tOrderRow *rowCus;
tSupplierOrder *supOrd, *firstSupOrd, *currentSupOrd, *auxSupOrd;
// Inicialitzem la llista
supOrd
= malloc(sizeof(tSupplierOrder
)); // so = NULL;
firstSupOrd = supOrd;
currentSupOrd = supOrd;
// Creem un tSupplierOrder per a cadascun dels diferents proveidors que tenim en la comanda de client
// Buscar primer tOrderRow (firstItem) i recorrer tota llista
rowCus = co.firstItem;
while(rowCus != NULL)
{
auxSupOrd = firstSupOrd;
// Comprovem si ja tenim inicialitzada una comanda a proveidor
while((auxSupOrd != NULL) && (rowCus->idProv != auxSupOrd->idSupplier))
{
auxSupOrd = auxSupOrd->nextSupOrder;
}
// Comprovem si hem trobat comanda a proveidor ja inicialitzada
if(rowCus->idProv == auxSupOrd->idSupplier)
{
//Afegim un nou tOrderRow a la comanda a proveidor
rowCus->nextOrderRowSup = NULL;
auxSupOrd->currItem->nextOrderRowSup = rowCus;
auxSupOrd->currItem = auxSupOrd->currItem->nextOrderRowSup;
auxSupOrd->totalPrice += rowCus->unit * rowCus->unitCostPrice;
}
else
{
// No hem trobat el proveidor a la llista, hem de crear una nova comanda
currentSupOrd
->nextSupOrder
= malloc(sizeof(tSupplierOrder
)); currentSupOrd->nextSupOrder = newSupplierOrder();
currentSupOrd = currentSupOrd->nextSupOrder;
currentSupOrd->idOrder = getNewSupIdOrder(co.idOrder, currentSupOrd->idSupplier);
currentSupOrd->idSupplier = rowCus->idProv;
get_current_date(¤tSupOrd->createdDate);
rowCus->nextOrderRowSup = NULL;
currentSupOrd->firstItem = rowCus;
currentSupOrd->currItem = rowCus;
currentSupOrd->totalPrice = rowCus->unit * rowCus->unitCostPrice;
}
rowCus = rowCus->nextOrderRow;
}
}
/*****************************************************************************
Operacions especials delivery_time i warehouse_stock.
******************************************************************************/
tFurniture *get_furniture( tShop ts, int idSup, int idFur)
{
tSupplier sup;
tFurniture *fur;
int i;
fur = NULL; //Important per si no trobem proveidor o moble
i = 0;
// Busquem el proveidor
while ((i<MAX_SUPPLIERS) && (ts.suppliers[i].idSupplier != idSup))
i++;
if(ts.suppliers[i].idSupplier == idSup)
{
sup = ts.suppliers[i];
// Busquem el moble
fur = sup.firstFur;
while((fur != NULL) && (fur->idFurniture !=idFur))
fur = fur->nextFur;
// Quan sortim del bucle while o hem trobat el moble o estem al final de la llista
}
return fur;
}
/*****
delivery_time: Calcula el termini d'entrega d'una comanda client.
Depèn del màxim termini entrega (per part dels proveïdors) de tota la comanda
******/
int delivery_time(tShop ts, tCustomerOrder co)
{
int maxDays;
tOrderRow *row;
tFurniture *fur;
maxDays = 0;
// Per a cada moble en la comanda de client busquem el corresponent tFurniture
row = co.firstItem;
while (row != NULL)
{
// Busquem moble
fur = get_furniture(ts, row->idProv, row->idFur);
if(fur!=NULL)
{
// Si el termini entrega es major que el maxim, actualitzem el maxim
if(maxDays < fur->deliveryTime)
maxDays = fur->deliveryTime;
}
// Busquem seguent moble
row = row->nextOrderRow;
}
return maxDays;
}
/*****
warehouse_stock: Estoc del magatzem, és a dir, llistat de comandes rebudes i pendents d'entregar al client.
Entenem que llistats surten per pantalla
*****/
void warehouse_stock(tShop ts)
{
tCustomerOrder *custOrder;
printf("WAREHOUSE STOCK:\n\n"); custOrder = ts.firstCustOrder;
while(custOrder != NULL)
{
// Imprimim per pantalla la comanda
if(custOrder->state == inWarehouse)
{
printf("ID:%d\tCUSTOMER:%s\tDATE:%d/%d/%d\tSTATE:%s\n", custOrder->idOrder, custOrder->nameCust,
custOrder->createdDate.day, custOrder->createdDate.month,
custOrder->createdDate.year, custOrder->state);
}
custOrder = custOrder->nextCustOrder;
}
}
/*****************************************************************************
funció sort_supOrder que ordena la llista de comandes a proveïdors
de manera descendent, segons el preu total de la comanda.
Per a la ordenació utilitza el mètode de classificació Merge Sort.
******************************************************************************/
/*****
combine: funcio auxiliar que combina dues llistes de manera ordenada
*****/
void combine (tSupplierOrder out[], int left, int middle, int right, int size)
{
int r, i, j;
tSupplierOrder outAux[size];
r = left;
i = left;
j = middle + 1;
while ((i <= middle) && (j <= right) && (j < size))
{
if(out[i].totalPrice > out[j].totalPrice)
{
outAux[r] = out[i];
i++;
r++;
}
else
{
outAux[r] = out[j];
j++;
r++;
}
}
while(i <= middle)
{
outAux[r] = out[i];
i++;
r++;
}
while(j <= right)
{
outAux[r] = out[j];
j++;
r++;
}
for(i=left; i<=right; i++)
out[i] = outAux[i];
}
/*****
merge_sort: funcio auxiliar recursiva que aplica el metode Merge Sort
*****/
void merge_sort (tSupplierOrder s[], int left, int right, int size)
{
int middle;
tSupplierOrder *listLeft, *listRight;
if (left < right)
{
middle = (left + right) / 2;
merge_sort(s, left, middle, size);
merge_sort(s, middle+1, right, size);
combine(s, left, middle, right, size);
}
}
void sort_supOrder(tShop *t)
{
int left, right, i, rightAux;
tSupplierOrder *aux, *aux2;
left = 0;
right = 0;
// Calculem el numero de comandes de proveidors que tenim i ho desem right (limit dret)
aux = t->firstSupOrder;
while(aux != NULL)
{
right++;
aux = aux->nextSupOrder;
}
// Creem una copia de la llista en el vector i anem esborrant i alliberant memoria
tSupplierOrder supOrders[right];
aux = t->firstSupOrder;
for(i=0; i<right; i++)
{
supOrders[i] = *aux;
aux2 = aux;
aux = aux->nextSupOrder;
}
// Cridem a la funcio merge_sort amb el nou vector i els limits Esquerre i Dret
rightAux = right;
merge_sort(supOrders, left, right-1, right);
// Mostrem resultats per pantalla
for(i=0; i<right; i++)
{
printf("idOrder:%d\ttotalPrice:%f\n", supOrders
[i
].
idOrder, supOrders
[i
].
totalPrice); }
// Restaurem llista i actualitzem apuntadors
aux
= malloc(sizeof(tSupplierOrder
)); t->firstSupOrder = aux;
for(i=0; i<right-1; i++)
{
*aux = supOrders[i];
aux
->nextSupOrder
= malloc(sizeof(tSupplierOrder
)); aux = aux->nextSupOrder;
}
*aux = supOrders[i];
aux->nextSupOrder = NULL;
}