static const char *pname;
static char *finame;
static FILE *fi;
-static int verbose=0,tree=0;
+static int verbose=0,tree=0,doaverage=0;
static char *formtotal=DEF_FORMTOTAL;
static char buf[LINE_MAX];
static int line=0;
static enum { SORT_NO,SORT_TIMETOT,SORT_STORES } sortby=SORT_TIMETOT;
+static unsigned lifetime_days=0;
static void usage(void)
{
-s, --stores\t\tSort the result by stores count\n\
-T, --timetot\t\tSort the result by total time (default)\n\
-t, --tree\t\tOrganize data as hierarchy tree\n\
+ -a, --average\t\tDisplay all times as average-per-day value\n\
-c, --condition\tDefine condition variable\n\
-f, --formtotal\tFormat \"Total\" column (\"text *val/val:width text\")\n\
-r, --rule\t\tAdd to the end of .rc file this rule (':'->'\\t')\n\
{"stores" ,0,0,'s'},
{"timetot" ,0,0,'T'},
{"tree" ,0,0,'t'},
+{"average" ,0,0,'a'},
{"condition",1,0,'c'},
{"formtotal",1,0,'f'},
{"rule" ,1,0,'r'},
static int dumpaction(const struct action *action)
{
-int tot FAKEUSE,mins FAKEUSE,hours FAKEUSE,days FAKEUSE,origtot;
+int tot,mins FAKEUSE,hours FAKEUSE,days FAKEUSE,origtot;
char *s,fmt[]="%?d";
if (action) {
tot=(action->timetot+30)/60;
+ if (doaverage && lifetime_days)
+ tot/=lifetime_days;
mins=tot; hours=mins/60; days=hours/24;
mins%=60; hours%=24;
- origtot=tot;
}
- else origtot=0;
+ else tot=0;
+ origtot=tot;
for (s=formtotal;*s;s++)
switch (*s) {
case '*': case '/': {
else origtot++;
}
if (action)
- printf("=%02d/%02d:%02d\t%4d\t%s\n",days,hours,mins,
+ printf("=%03d/%02d:%02d %4d\t%s\n",days,hours,mins,
action->stores,action->what);
return(origtot);
}
int totalwidth=dumpaction(NULL);
while (totalwidth-->5) putchar(' ');
- puts("Total Da Hr Mi\tStor\tDescription");
+ puts("Total Day Hr Mi Stor\tDescription");
if (!(sorta=malloc(sizeof(*sorta)*hashtable_tot))) {
fprintf(ERRH1"malloc() of %d pointers"ERRNO1,ERRH2,hashtable_tot,ERRNO2);
exit(EXIT_FAILURE);
{
unsigned r=57;
- while (*s) r=r*7+11*(*s++);
+ while (*s) r=r*7+11*toupper(*s++);
return r;
}
storeone(what,length);
}
-static void hit(time_t t)
+static void hit(time_t t,char *bufaction)
{
static time_t last=-1;
static char bufbackup[sizeof(buf)];
char *acts[ACTS_MAX],*s;
int timetot,acti,i;
- if (verbose) printf("hit: %ld: %s\n",t,buf+6);
+ if (verbose) printf("hit: %ld: %s\n",t,bufaction);
if (last!=-1) {
if (t<last) {
fprintf(ERRH1"Time goes backward"WHERE1,ERRH2,WHERE2);
t=last;
}
- acts[0]=bufbackup+6;
+ acts[0]=bufbackup;
acti=1;
while ((s=strchr(acts[acti-1],'+'))) {
*s='\0';
for (i=0;i<acti;i++)
store(acts[i],calctime(timetot,i,acti));
}
- strcpy(bufbackup,buf);
+ strcpy(bufbackup,bufaction);
last=t;
}
{
int optc;
time_t basetime=-1,currtime;
-int hour,min;
+int hour,min,sec;
pname=argv[0];
- while ((optc=getopt_long(argc,argv,"b:pw:qusTtc:f:r:vhV",longopts,NULL))!=EOF) switch (optc) {
+ while ((optc=getopt_long(argc,argv,"b:pw:qusTtac:f:r:vhV",longopts,NULL))!=EOF) switch (optc) {
case 'u':
sortby=SORT_NO;
case 't':
tree=1;
break;
+ case 'a':
+ doaverage=1;
+ break;
case 'c':
if (iscondition(optarg))
fprintf(ERRH1"Condition \"%s\" already set!\n",ERRH2,optarg);
#undef WANTED
basetime=t;
store(MARK_DAY,0);
+ lifetime_days++;
continue;
}
- if (!isdigit(buf[0]) || !isdigit(buf[1]) || buf[2]!=':' || !isdigit(buf[3]) || !isdigit(buf[4]) || buf[5]!='-'
- || sscanf(buf,"%d:%d-",&hour,&min)!=2
+ if (!(isdigit(buf[0]) && isdigit(buf[1]) && buf[2]==':' && isdigit(buf[3]) && isdigit(buf[4])
+ && (buf[5]=='-' || (buf[5]==':' && isdigit(buf[6]) && isdigit(buf[7]) && buf[8]=='-'))
+ )
+ || (sec=0,sscanf(buf,(buf[5]=='-'?"%d:%d-":"%d:%d:%d-"),&hour,&min,&sec)!=2+(buf[5]==':'))
|| hour<0 || hour>23
|| min <0 || min >59
+ || sec <0 || sec >59
) {
fprintf(ERRH1"Incorrect day-time \"%s\""WHERE1,ERRH2,buf,WHERE2);
exit(EXIT_FAILURE);
fprintf(ERRH1"Day-time found but no basetime timestamp set"WHERE1,ERRH2,WHERE2);
exit(EXIT_FAILURE);
}
- currtime=basetime+(hour*60+min)*60;
- hit(currtime);
+ currtime=basetime+(hour*60+min)*60+sec;
+ hit(currtime,buf+(buf[5]=='-'?6:9));
}
if (!feof(fi) || ferror(fi)) {