From fccf61571895529d106dc42d98595af77a915e56 Mon Sep 17 00:00:00 2001 From: akool Date: Tue, 16 Mar 1999 17:37:08 +0000 Subject: [PATCH] - isdnlog Version 3.07 - Michael Reinelt's patch as of 16Mar99 06:58:58 - fix a fix from yesterday with sondernummern - ignore "" COLP/CLIP messages - dont show a LCR-Hint, if same price --- isdnlog/Makefile.in | 11 +- isdnlog/holiday-at.dat | 2 + isdnlog/holiday-ch.dat | 2 + isdnlog/holiday-de.dat | 2 + isdnlog/holiday-nl.dat | 5 + isdnlog/isdnlog/processor.c | 24 ++- isdnlog/isdnlog/takt_de.c | 23 ++- isdnlog/tools/holiday.c | 48 ++++-- isdnlog/tools/holiday.h | 11 +- isdnlog/tools/rate.c | 329 +++++++++++++++++++++--------------- isdnlog/tools/rate.h | 32 +++- 11 files changed, 318 insertions(+), 171 deletions(-) diff --git a/isdnlog/Makefile.in b/isdnlog/Makefile.in index 874226ec..a2f53cc9 100644 --- a/isdnlog/Makefile.in +++ b/isdnlog/Makefile.in @@ -1,4 +1,4 @@ -## $Id: Makefile.in,v 1.59 1999/03/15 21:27:30 akool Exp $ +## $Id: Makefile.in,v 1.60 1999/03/16 17:37:08 akool Exp $ ## ## ISDN accounting for isdn4linux. ## @@ -19,6 +19,13 @@ ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ## ## $Log: Makefile.in,v $ +## Revision 1.60 1999/03/16 17:37:08 akool +## - isdnlog Version 3.07 +## - Michael Reinelt's patch as of 16Mar99 06:58:58 +## - fix a fix from yesterday with sondernummern +## - ignore "" COLP/CLIP messages +## - dont show a LCR-Hint, if same price +## ## Revision 1.59 1999/03/15 21:27:30 akool ## - isdnlog Version 3.06 ## - README: explain some terms about LCR, corrected "-c" Option of "isdnconf" @@ -464,7 +471,7 @@ SERVICEFILE = /etc/services # DON'T EDIT BELOW THIS LINE ###################################################################### -VERSION = 3.06 +VERSION = 3.07 MANPAGES = isdnlog/callerid.conf.5 isdnlog/isdn.conf.5 isdnlog/isdnformat.5 isdnlog/isdnlog.5 isdnlog/isdnlog.8 isdnlog/isdnlog.users.5 isdnrep/isdnrep.1 isdnconf/isdnconf.1 diff --git a/isdnlog/holiday-at.dat b/isdnlog/holiday-at.dat index 3ba2ecc7..2e720ef0 100644 --- a/isdnlog/holiday-at.dat +++ b/isdnlog/holiday-at.dat @@ -1,3 +1,5 @@ +V:1.0-Austria [15-Mar-1999] + W:1 Montag W:2 Dienstag W:3 Mittwoch diff --git a/isdnlog/holiday-ch.dat b/isdnlog/holiday-ch.dat index a94e9030..f3ae46a3 100644 --- a/isdnlog/holiday-ch.dat +++ b/isdnlog/holiday-ch.dat @@ -1,3 +1,5 @@ +V:1.0-Switzerland [15-Mar-1999] + W:1 Montag W:2 Dienstag W:3 Mittwoch diff --git a/isdnlog/holiday-de.dat b/isdnlog/holiday-de.dat index 9f7063a4..b024dae6 100644 --- a/isdnlog/holiday-de.dat +++ b/isdnlog/holiday-de.dat @@ -1,3 +1,5 @@ +V:1.0-Germany [15-Mar-1999] + W:1 Montag W:2 Dienstag W:3 Mittwoch diff --git a/isdnlog/holiday-nl.dat b/isdnlog/holiday-nl.dat index 619edeb3..770d65c9 100644 --- a/isdnlog/holiday-nl.dat +++ b/isdnlog/holiday-nl.dat @@ -1,3 +1,8 @@ +V:0.9-Netherlands [15-Mar-1999] + +# Fixme: +# these need to be translated + W:1 Mondag W:2 Thuesdag W:3 Wednesdag diff --git a/isdnlog/isdnlog/processor.c b/isdnlog/isdnlog/processor.c index c779afdd..46bfa509 100644 --- a/isdnlog/isdnlog/processor.c +++ b/isdnlog/isdnlog/processor.c @@ -1,4 +1,4 @@ -/* $Id: processor.c,v 1.43 1999/03/15 21:27:58 akool Exp $ +/* $Id: processor.c,v 1.44 1999/03/16 17:37:18 akool Exp $ * * ISDN accounting for isdn4linux. (log-module) * @@ -19,6 +19,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: processor.c,v $ + * Revision 1.44 1999/03/16 17:37:18 akool + * - isdnlog Version 3.07 + * - Michael Reinelt's patch as of 16Mar99 06:58:58 + * - fix a fix from yesterday with sondernummern + * - ignore "" COLP/CLIP messages + * - dont show a LCR-Hint, if same price + * * Revision 1.43 1999/03/15 21:27:58 akool * - isdnlog Version 3.06 * - README: explain some terms about LCR, corrected "-c" Option of "isdnconf" @@ -756,8 +763,10 @@ static void buildnumber(char *num, int oc3, int oc3a, char *result, int version, if (*sondernummer == UNKNOWN) *sondernummer = is_sondernummer(num, *provider); - if (*sondernummer == UNKNOWN) - *sondernummer = !memcmp(num, "019", 3); /* anything like 019xx is a Sondernummer! */ + if (*sondernummer == UNKNOWN) { + if (!memcmp(num, "019", 3)) /* anything like 019xx is a Sondernummer! */ + *sondernummer = 1; + } /* if */ } /* if */ @@ -2417,10 +2426,15 @@ static void decode(int chan, register char *p, int type, int version, int tei) *pd = 0; + if (!*s) { + info(chan, PRT_SHOWNUMBERS, STATE_RING, "COLP *INVALID* -- ignored!"); + break; + } /* if */ + if (dual && !*s) strcpy(s, call[chan].onum[CALLED]); else - strcpy(call[chan].onum[CALLED], s); + strcpy(call[chan].onum[CALLED], s); /* bei "national" numbers evtl. fuehrende "0" davor */ if (((oc3 & 0x70) == 0x20) && (*s != '0')) { @@ -2431,7 +2445,7 @@ static void decode(int chan, register char *p, int type, int version, int tei) buildnumber(s, oc3, oc3a, call[chan].num[CALLED], version, &call[chan].provider, &call[chan].sondernummer[CALLED], &call[chan].intern[CALLED], 0, CALLED); if (!dual) - strcpy(call[chan].vnum[CALLED], vnum(chan, CALLED)); + strcpy(call[chan].vnum[CALLED], vnum(chan, CALLED)); #ifdef Q931 if (q931dmp && (*call[chan].vnum[CALLED] != '?') && *call[chan].vorwahl[CALLED] && oc3 && ((oc3 & 0x70) != 0x40)) { diff --git a/isdnlog/isdnlog/takt_de.c b/isdnlog/isdnlog/takt_de.c index eaa679b1..c96cad38 100644 --- a/isdnlog/isdnlog/takt_de.c +++ b/isdnlog/isdnlog/takt_de.c @@ -1,4 +1,4 @@ -/* $Id: takt_de.c,v 1.13 1999/03/15 21:28:04 akool Exp $ +/* $Id: takt_de.c,v 1.14 1999/03/16 17:37:27 akool Exp $ * * ISDN accounting for isdn4linux. (log-module) * @@ -19,6 +19,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: takt_de.c,v $ + * Revision 1.14 1999/03/16 17:37:27 akool + * - isdnlog Version 3.07 + * - Michael Reinelt's patch as of 16Mar99 06:58:58 + * - fix a fix from yesterday with sondernummern + * - ignore "" COLP/CLIP messages + * - dont show a LCR-Hint, if same price + * * Revision 1.13 1999/03/15 21:28:04 akool * - isdnlog Version 3.06 * - README: explain some terms about LCR, corrected "-c" Option of "isdnconf" @@ -800,7 +807,7 @@ void price(int chan, char *hint, int viarep) if (call[chan].tarifknown && !viarep) { cheapest = UNKNOWN; - payx = 99999.9; + payx = call[chan].pay; for (p = 0; p < MAXPROVIDER; p++) { payy = tpreis(p, call[chan].zone, call[chan].tz, tm->tm_hour, duration); @@ -826,17 +833,17 @@ void price(int chan, char *hint, int viarep) WAEHRUNG, double2str(call[chan].pay - payx, 6, 3, DEB)); - if ((call[chan].provider != preselect) && (prepreis != -1.00)) + if ((call[chan].provider != preselect) && (prepreis != -1.00) && (prepreis != call[chan].pay)) sprintf(sy, " saving vs. preselect (010%02d:%s) %s %s", preselect, t[preselect].Provider, WAEHRUNG, double2str(prepreis - call[chan].pay, 6, 3, DEB)); - if ((call[chan].hint != UNKNOWN) && (call[chan].hint != cheapest)) - sprintf(sz, " saving vs. hint (010%02d:%s) %s %s", - call[chan].hint, t[call[chan].hint].Provider, - WAEHRUNG, - double2str(hintpreis - call[chan].pay, 6, 3, DEB)); + if ((call[chan].hint != UNKNOWN) && (call[chan].hint != cheapest)) + sprintf(sz, " saving vs. hint (010%02d:%s) %s %s", + call[chan].hint, t[call[chan].hint].Provider, + WAEHRUNG, + double2str(hintpreis - call[chan].pay, 6, 3, DEB)); if (*sx || *sy || *sz) sprintf(hint, "HINT: %s%s%s LCR:%s", sx, sy, sz, ((cheapest == call[chan].provider) ? "OK" : "FAILED")); diff --git a/isdnlog/tools/holiday.c b/isdnlog/tools/holiday.c index 527cb0a8..50a10952 100644 --- a/isdnlog/tools/holiday.c +++ b/isdnlog/tools/holiday.c @@ -1,4 +1,4 @@ - /* $Id: holiday.c,v 1.1 1999/03/14 12:16:23 akool Exp $ + /* $Id: holiday.c,v 1.2 1999/03/16 17:38:03 akool Exp $ * * Feiertagsberechnung * @@ -19,6 +19,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: holiday.c,v $ + * Revision 1.2 1999/03/16 17:38:03 akool + * - isdnlog Version 3.07 + * - Michael Reinelt's patch as of 16Mar99 06:58:58 + * - fix a fix from yesterday with sondernummern + * - ignore "" COLP/CLIP messages + * - dont show a LCR-Hint, if same price + * * Revision 1.1 1999/03/14 12:16:23 akool * - isdnlog Version 3.04 * - general cleanup @@ -63,7 +70,7 @@ #include #include "holiday.h" -#define LENGTH 80 /* max length of lines in data file */ +#define LENGTH 120 /* max length of lines in data file */ typedef unsigned int julian; @@ -113,7 +120,7 @@ static void julian2date(julian jd, int *yp, int *mp, int *dp) { julian j,c,y,m,d; - j=d*4-1; + j=jd*4-1; c=(j/146097)*100; d=(j%146097)/4; y=(4*d+3)/1461; @@ -179,12 +186,14 @@ void exitHoliday(void) Holiday=NULL; } -int initHoliday(char *path) +int initHoliday(char *path, char **msg) { FILE *stream; + int i,m,d; char *s, *date, *name; char buffer[LENGTH]; - int i,m,d; + char version[LENGTH]=""; + static char message[LENGTH]; exitHoliday(); @@ -241,12 +250,19 @@ int initHoliday(char *path) nHoliday++; break; + case 'V': /* V:xxx Version der Datenbank */ + strcpy(version, s+2); + break; + default: warning("Unknown tag '%c'", *s); } } fclose(stream); + if (msg) snprintf (*msg=message, LENGTH, "Holiday Version %s loaded [%d entries from %s]", + version, nHoliday, path); + return nHoliday; } @@ -255,12 +271,12 @@ int isHoliday(struct tm *tm, char **name) int i; julian easter, day; - day=date2julian(tm->tm_year,tm->tm_mon,tm->tm_mday); - easter=getEaster(tm->tm_year); + day=date2julian(tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday); + easter=getEaster(tm->tm_year+1900); for (i=0; itm_mon && Holiday[i].day==tm->tm_mday)) { + (Holiday[i].month==tm->tm_mon+1 && Holiday[i].day==tm->tm_mday)) { if(name) *name=Holiday[i].name; return 1; @@ -276,29 +292,31 @@ int getDay(struct tm *tm, char **name) if (isHoliday(tm, name)) return HOLIDAY; - day=(date2julian(tm->tm_year,tm->tm_mon,tm->tm_mday)-6)%7+1; + day=(date2julian(tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday)-6)%7+1; if (name) *name=Weekday[day-1]; return day; } -#ifdef STANDALONE +#ifdef HOLITEST void main (int argc, char *argv[]) { int i, d; - char *name; + char *msg, *name; struct tm tm; - printf ("%d Feiertage\n", initHoliday("../holiday-de.dat")); + + initHoliday("../holiday-at.dat", &msg); + printf ("%s\n", msg); for (i=1; i < argc; i++) { tm.tm_mday=atoi(strsep(argv+i,".")); - tm.tm_mon=atoi(strsep(argv+i,".")); - tm.tm_year=atoi(strsep(argv+i,".")); + tm.tm_mon=atoi(strsep(argv+i,"."))-1; + tm.tm_year=atoi(strsep(argv+i,"."))-1900; d=getDay(&tm,&name); - printf ("%d.%d.%d\t%d=%s\n", tm.tm_mday,tm.tm_mon, tm.tm_year,d,name); + printf ("%02d.%02d.%04d\t%d=%s\n", tm.tm_mday,tm.tm_mon+1,tm.tm_year+1900,d,name); } } #endif diff --git a/isdnlog/tools/holiday.h b/isdnlog/tools/holiday.h index 02c20eaa..17e956c3 100644 --- a/isdnlog/tools/holiday.h +++ b/isdnlog/tools/holiday.h @@ -1,4 +1,4 @@ -/* $Id: holiday.h,v 1.1 1999/03/14 12:16:41 akool Exp $ +/* $Id: holiday.h,v 1.2 1999/03/16 17:38:07 akool Exp $ * * Feiertagsberechnung * @@ -19,6 +19,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: holiday.h,v $ + * Revision 1.2 1999/03/16 17:38:07 akool + * - isdnlog Version 3.07 + * - Michael Reinelt's patch as of 16Mar99 06:58:58 + * - fix a fix from yesterday with sondernummern + * - ignore "" COLP/CLIP messages + * - dont show a LCR-Hint, if same price + * * Revision 1.1 1999/03/14 12:16:41 akool * - isdnlog Version 3.04 * - general cleanup @@ -45,7 +52,7 @@ #define SUNDAY 7 #define HOLIDAY 8 -int initHoliday(char *path); +int initHoliday(char *path, char **msg); void exitHoliday(void); int isHoliday(struct tm *tm, char **name); int getDay(struct tm *tm, char **name); diff --git a/isdnlog/tools/rate.c b/isdnlog/tools/rate.c index 836b1130..dcc5aac2 100644 --- a/isdnlog/tools/rate.c +++ b/isdnlog/tools/rate.c @@ -1,4 +1,4 @@ -/* $Id: rate.c,v 1.1 1999/03/14 12:16:42 akool Exp $ +/* $Id: rate.c,v 1.2 1999/03/16 17:38:09 akool Exp $ * * Tarifdatenbank * @@ -19,6 +19,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: rate.c,v $ + * Revision 1.2 1999/03/16 17:38:09 akool + * - isdnlog Version 3.07 + * - Michael Reinelt's patch as of 16Mar99 06:58:58 + * - fix a fix from yesterday with sondernummern + * - ignore "" COLP/CLIP messages + * - dont show a LCR-Hint, if same price + * * Revision 1.1 1999/03/14 12:16:42 akool * - isdnlog Version 3.04 * - general cleanup @@ -39,33 +46,17 @@ * void exitRate(void) * deinitialisiert die Tarifdatenbank * - * void initRate(char *info) - * initialisiert die Tarifdatenbank, liefert Versionsinfo in `info' - * zurueck + * void initRate(char *conf, char *dat, char **msg) + * initialisiert die Tarifdatenbank * - * char *Providername(int prefix) - * liefert den Providernamen fuer Kennzahl `prefix', oder NULL, falls - * unbekannt + * int getRate(RATE*Rate, char **msg) + * liefert die Tarifberechnung in *Rate, UNKNOWN im + * Fehlerfall, *msg enthält die Fehlerbeschreibung * - * char *Zonename(int prefix, int zone) - * liefert den Zonennamen fuer Provider `prefix', oder NULL, falls - * unbekannt - * - * int taktlaenge(int chan, char *why) - * liefert fuer die aktuell laufende Verbindung in `chan' - * die Laenge eines Tariftaktes in Sekunden, sowie evtl. in `why' - * eine textuelle Begruendung - * - * void preparecint(int chan, char *msg, char *hint) - * fuellt die aktuell laufende Verbindung in `chan' mit allen - * fuer die weitere Taktberechnung noetigen Daten - * liefert evtl. in `msg' sowie `hint' textuelle Informationen - * fuer die LCR-Optimierung - * - * void price(int chan, char *hint) - * berechnet fuer die gerade beendete Verbindung in `chan' den - * Endpreis, stellt diesen in `chan', und liefert in `hint' evtl. - * textuelle Informationen fuer die LCR-Optimierung + * int getLeastCost (RATE *Rate) + * berechnet den billigsten Provider zu *Rate, Rückgabewert + * ist der Prefix des billigsten Providers oder UNKNOWN wenn + * *Rate bereits den billigsaten Tarif enthält * */ @@ -77,6 +68,8 @@ #include #include #include +#include +#include "holiday.h" #include "rate.h" #define MAXPROVIDER 100 @@ -97,13 +90,13 @@ typedef struct { bitfield Hour; int nUnit; UNIT *Unit; -} RATE; +} HOUR; typedef struct { int used; char *Name; - int nRate; - RATE *Rate; + int nHour; + HOUR *Hour; } ZONE; typedef struct { @@ -115,7 +108,6 @@ typedef struct { } PROVIDER; static PROVIDER Provider[MAXPROVIDER]; -static int use[MAXPROVIDER]; static int line=0; static void warning (char *fmt, ...) @@ -157,12 +149,12 @@ void exitRate(void) for (j=0; jzone2) { - i=zone2; zone2=zone1; zone1=i; + if (zone>=Provider[prefix].nZone) { + Provider[prefix].Zone=realloc(Provider[prefix].Zone, (zone+1)*sizeof(ZONE)); + Provider[prefix].nZone = zone+1; } - if (zone2>=Provider[prefix].nZone) { - Provider[prefix].Zone=realloc(Provider[prefix].Zone, (zone2+1)*sizeof(ZONE)); - Provider[prefix].nZone = zone2+1; - } - for (i=zone1; i<=zone2; i++) { - Provider[prefix].Zone[i].used=1; - Provider[prefix].Zone[i].Name=strdup(strip(s)); - Provider[prefix].Zone[i].nRate=0; - Provider[prefix].Zone[i].Rate=NULL; + Provider[prefix].Zone[zone].used=1; + Provider[prefix].Zone[zone].Name=strdup(strip(s)); + Provider[prefix].Zone[zone].nHour=0; + Provider[prefix].Zone[zone].Hour=NULL; nZone++; - } break; case 'T': /* T:d-d/h-h=p/s:t[=]Bezeichnung */ if (ignore) continue; - if (zone1 == UNKNOWN) { + if (zone == UNKNOWN) { warning ("Unexpected tag '%c'", *s); break; } @@ -353,6 +340,7 @@ int initRate(char *conf, char *dat, char *msg) } } + hour=0; while (1) { if (*s=='*') { /* jede Stunde */ hour |= 0xffffff; /* alles 1er */ @@ -382,43 +370,43 @@ int initRate(char *conf, char *dat, char *msg) warning ("I'm sorry, I don't understand this line..."); continue; } - for (i=zone1; i<=zone2; i++) { - t=Provider[prefix].Zone[i].nRate++; - Provider[prefix].Zone[i].Rate = realloc(Provider[prefix].Zone[i].Rate, (t+1)*sizeof(RATE)); - Provider[prefix].Zone[i].Rate[t].Name=NULL; - Provider[prefix].Zone[i].Rate[t].Day=day; - Provider[prefix].Zone[i].Rate[t].Hour=hour; - Provider[prefix].Zone[i].Rate[t].nUnit=0; - Provider[prefix].Zone[i].Rate[t].Unit=NULL; - } + t=Provider[prefix].Zone[zone].nHour++; + Provider[prefix].Zone[zone].Hour = realloc(Provider[prefix].Zone[zone].Hour, (t+1)*sizeof(HOUR)); + Provider[prefix].Zone[zone].Hour[t].Name=NULL; + Provider[prefix].Zone[zone].Hour[t].Day=day; + Provider[prefix].Zone[zone].Hour[t].Hour=hour; + Provider[prefix].Zone[zone].Hour[t].nUnit=0; + Provider[prefix].Zone[zone].Hour[t].Unit=NULL; while (1) { price=strtod(s,&s); duration=1; - delay=0; + delay=UNKNOWN; if (*s=='/') - duration=strtol(s+1,&s,10); + duration=strtod(s+1,&s); if (*s==':') delay=strtol(s+1,&s,10); - - for (i=zone1; i<=zone2; i++) { - t=Provider[prefix].Zone[i].nRate-1; - u=Provider[prefix].Zone[i].Rate[t].nUnit++; - Provider[prefix].Zone[i].Rate[t].Unit=realloc(Provider[prefix].Zone[i].Rate[t].Unit, (u+1)*sizeof(UNIT)); - Provider[prefix].Zone[i].Rate[t].Unit[u].Duration=duration; - Provider[prefix].Zone[i].Rate[t].Unit[u].Delay=delay; - Provider[prefix].Zone[i].Rate[t].Unit[u].Price=price; - nRate++; + if (*s==',' && delay==UNKNOWN) + delay=duration; + if (*s!=',' && delay!=UNKNOWN){ + warning("last rate must not have a delay, will be ignored!"); + delay=UNKNOWN; } + t=Provider[prefix].Zone[zone].nHour-1; + u=Provider[prefix].Zone[zone].Hour[t].nUnit++; + Provider[prefix].Zone[zone].Hour[t].Unit=realloc(Provider[prefix].Zone[zone].Hour[t].Unit, (u+1)*sizeof(UNIT)); + Provider[prefix].Zone[zone].Hour[t].Unit[u].Duration=duration; + Provider[prefix].Zone[zone].Hour[t].Unit[u].Delay=delay; + Provider[prefix].Zone[zone].Hour[t].Unit[u].Price=price; + nHour++; if (*s!=',') break; + s++; } if (*s=='=') s++; - for (i=zone1; i<=zone2; i++) { - t=Provider[prefix].Zone[i].nRate-1; - Provider[prefix].Zone[i].Rate[t].Name=strdup(strip(s)); - } + t=Provider[prefix].Zone[zone].nHour-1; + Provider[prefix].Zone[zone].Hour[t].Name=strdup(strip(s)); break; - case 'V': /* V:xxx Version der Ratedatenbank */ + case 'V': /* V:xxx Version der Datenbank */ strcpy(Version, s+2); break; @@ -428,81 +416,152 @@ int initRate(char *conf, char *dat, char *msg) } } fclose(stream); - sprintf (msg, "Rate Version %s loaded [%d Providers, %d Zones, %d Rates]", - Version, nProvider, nZone, nRate); + + if (msg) snprintf (*msg=message, LENGTH, "Rate Version %s loaded [%d Providers, %d Zones, %d Rates from %s]", + Version, nProvider, nZone, nHour, dat); return 0; } -char *Providername(int prefix) -{ - if (!Provider[prefix].used) return(NULL); - return(Provider[prefix].Name); -} - -char *Zonename(int prefix, int zone) -{ - if (!Provider[prefix].used) return(NULL); - if (zone<1 || zone>=Provider[prefix].nZone) return (NULL); - if (!Provider[prefix].Zone[zone].used) return (NULL); - return(Provider[prefix].Zone[zone].Name); -} - -static double tpreis(int prefix, int zone, int day, int hour, int duration) +int getRate(RATE *Rate, char **msg) { + static char message[LENGTH]; bitfield dayMask, hourMask; - RATE *Rate; + ZONE *Zone; + HOUR *Hour; UNIT *Unit; - double price; - int delay, i; + int prefix, zone, day, hour, i; + time_t now, run, end; + struct tm tm; - if (!Provider[prefix].used) return UNKNOWN; - if (!Provider[prefix].Zone[zone].used) return UNKNOWN ; + if (!Rate) + return UNKNOWN; - dayMask=1<<(day-1); - hourMask=1<Day & dayMask) && (Rate->Hour & hourMask)) - break; + prefix=Rate->prefix; + if (prefix<0 || prefix>MAXPROVIDER || !Provider[prefix].used) { + if (msg) snprintf(*msg=message, LENGTH, "unknown provider '%d'", prefix); + return UNKNOWN; } - if (i==Provider[prefix].Zone[zone].nRate) return UNKNOWN; - - i = 1; - price = 0.0; - delay = 0; - Unit = Rate->Unit; - while (duration>0) { - duration -= Unit->Duration; - delay += Unit->Duration; - price += Unit->Price; - if ((delay >= Unit->Delay) && (i < Rate->nUnit)) + + zone=Rate->zone; + if (zone<1 || zone>=Provider[prefix].nZone || !Provider[prefix].Zone[zone].used) { + if (msg) snprintf(*msg=message, LENGTH, "unknown zone '%d'", zone); + return UNKNOWN; + } + + Zone=&Provider[prefix].Zone[zone]; + Rate->Provider=Provider[prefix].Name; + Rate->Zone=Zone->Name; + Rate->Units=0; + Rate->Duration=0; + Rate->Price=0; + Rate->Charge=0; + Rate->Rest=0; + + Hour=NULL; + Unit=NULL; + hour=UNKNOWN; /* Stundenwechsel erzwingen */ + now=mktime(&Rate->start); + end=mktime(&Rate->now); + Rate->Time=end-now; + run=0; + while (end>=now) { + tm=*localtime(&now); + if (hour!=tm.tm_hour) { /* Neuberechnung bei Stundenwechsel */ + hour=tm.tm_hour; + day=getDay(&tm, &Rate->Day); + dayMask=1<<(day-1); + hourMask=1<nHour; i++) { + Hour = &Zone->Hour[i]; + if ((Hour->Day & dayMask) && (Hour->Hour & hourMask)) + break; + } + if (i==Zone->nHour) { + if (msg) snprintf(*msg=message, LENGTH, + "no rate found for provider=%d zone=%d day=%d hour=%d", + prefix, zone, day, tm.tm_hour); + return UNKNOWN; + } + Rate->Hour=Hour->Name; + Unit=Hour->Unit; + } + + Rate->Duration=Unit->Duration; + Rate->Price=Unit->Price; + Rate->Charge+=Unit->Price; + Rate->Rest+=Unit->Duration; + now+=Unit->Duration; + run+=Unit->Duration; + if (Unit->Duration>0) + Rate->Units++; + if (Unit->Delay!=UNKNOWN && Unit->Delay<=run) Unit++; - } +} + Rate->Rest-=Rate->Time; + return 0; +} - return price; +int getLeastCost (RATE *Rate) +{ + int i, cheaper; + RATE LC; + + LC=*Rate; + cheaper=UNKNOWN; + + for (i=0; iprefix=i; + if (getRate(Rate, NULL)!=UNKNOWN && Rate->Charge