/* ＬＯＧ．ＥＸＥの集計を採るプログラム */
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>


#define	US		unsigned

#define	MINUTE	60
#define	HOUR	3600
#define	DAY		86400


/* 西向く侍小の月(^^;) */
int		MONTH[13]={0, 31,28,31,30, 31,30,31,31, 30,31,30,31};

/* グローバル変数 */
char	startKey[80];
char	endKey[80];




/* キーワードを得る */
int		keyword(char *key,char *str)
{
	char	*p;
	
	if ((p=strchr(str,'>'))==NULL)
	{
		*key=0;
		return(1);
	}
	else
	{
		strcpy(key,&p[1]);
		p=key;
		while(*p!='\n')
			p++;
		*p=0;
		return(0);
	}
}


/* キーワードの比較 */
int		keycmp(char *str,char *cmp)
{
	char	key[80];
	
	keyword(key,str);
	return(strcmp(key,cmp));
}




/* year年month月day日 hour:min:sec は 1974年1月1日 00:00:00から何秒? */
US long	time2sec(int year,int month,int day,int hour,int min,int sec)
{
	US long y,d;		/* year,day */
	int		u;			/* 閏年を何度経たか */
	int		i;			/* カウンタ */
	US long	s;			/* 秒数 */
	
	y=year-1974;
	u=(y+1)/4;
	
	d=365*y+u;
	if (year%4==0 && year%2000!=0 && month>2)		/* 閏年の補正 */
		d++;
	
	for (i=1;i<month;i++)		/* 月->日数 */
		d+=MONTH[i];
	
	d+=day-1;					/* 日->日数 */
	
	s= (US long)(d*DAY+ hour*HOUR + min*MINUTE + sec);
	return(s);
}




/* 文字列の秒数化 */
US long	str2time(char *str)
{
	int		y,m,d,h,min,s;
	char	ye[5],mo[3],da[3],ho[3],mi[3],se[3];
	US	long	ret;
	
	strncpy(ye,str,4);		ye[4]=0;	y=atoi(ye);
	strncpy(mo,str+5,2);	mo[2]=0;		m=atoi(mo);
	strncpy(da,str+8,2);	da[2]=0;		d=atoi(da);
	strncpy(ho,str+11,2);	ho[2]=0;		h=atoi(ho);
	strncpy(mi,str+14,2);	mi[2]=0;		min=atoi(mi);
	strncpy(se,str+17,2);	se[2]=0;		s=atoi(se);
	
	ret=time2sec(y,m,d,h,min,s);
	/*printf("%s/%s/%s %s:%s:%s\n",ye,mo,da,ho,mi,se);
	printf("%d/%d/%d %d:%d:%d %lu\n",y,m,d,h,min,s, ret);*/
	return(ret);
}




/* 秒数を見やすくする */
void	sec2str(char *str,US long sec)
{
	US long	d=0,h,mi,s;
	char	str2[16];
	
	strcpy(str2,"");
	h=sec/HOUR;	mi=sec%HOUR/MINUTE;	s=sec%HOUR%MINUTE;
	
	if (h>=24)
	{
		d=h/24;
		h=h%24;
		if (d>36)
			sprintf(str2," (約%2.1f年)",d/365.25);
	}
	
	if (d!=0)
		sprintf(str,"%lu日%lu時間%lu分%lu秒",d,h,mi,s);
	else if (h!=0)
		sprintf(str,"%lu時間%lu分%lu秒",h,mi,s);
	else if (mi!=0)
		sprintf(str,"%lu分%lu秒",mi,s);
	else 
		sprintf(str,"%lu秒",s);
	
	strcat(str,str2);
	return;
}





void	usage()
{
	puts("使用法: log_sum <logfile> <startKey> <endKey>");
	puts("詳しくはDOCを読んでね(^^;)");
	exit(1);
}




void	summarize(FILE *fp)
{
	char	str[256];
	int		sflag=0;
	int		count=2;
	US long sum_st=-1;	/* 集計を開始した時間 */
	US long sum_time;	/* 集計開始から終了までの時間 */
	US long	sum=0;	/* 合計起動時間 */
	US long	num=0;	/* 起動回数 */
	US long	en=0;	/* 終了回数 */
	US long st;		/* 最後にstartKeyが見つかった時間 */
	US long max=0;	/* 最長使用時間 */
	US long min=(US long)-1;	/* 最短時間 */
	US long	t;		/* 使用時間 */
	US long et;		/* 最後にendKeyが見つかった時間 */
	
	fgets(str,255,fp);
	if (keycmp(str,startKey)==0)
	{
		st=str2time(str);
		sum_st=st;
		num++;
		sflag=1;
	}
	
	while(feof(fp)==0)
	{
		fgets(str,255,fp);
		if (keycmp(str,endKey)==0 && sflag==1)
		{
			et=str2time(str);
			if (et<st)
			{
				printf("%d行付近に嘘っぽいデータがあります\n",count);
				printf("データ内容は...%s",str);
				exit(1);
			}
			t=et-st;
			sum += t;
			max = (t>max) ? t : max;
			min = (t<min) ? t : min;
			en++;
			sflag=0;
		}
		else if (keycmp(str,startKey)==0)
		{
			st= str2time(str);
			if (sum_st==-1)
				sum_st=st;
			num++;
			sflag=1;
		}
		count++;
		if ( (count & 31) == 0)
			fprintf(stderr,"集計中...%d\x1b[80D",count);
	}
	
	fprintf(stderr,"\n\n");
	
	printf("使用回数.......%lu回\n",num);
	printf("正常終了回数...%lu回\n",en);
	printf("異常終了回数...%lu回\n",num-en);
	
	printf("\n");
	sec2str(str,sum);
	printf("合計使用時間...%s\n",str);
	
	sec2str(str,sum/en);
	printf("平均使用時間...%s\n",str);
	
	sec2str(str,sum*(num/en));
	printf("実質使用時間...%s\n",str);
	
	sec2str(str,max);
	printf("最長使用時間...%s\n",str);
	
	sec2str(str,min);
	printf("最短使用時間...%s\n",str);
	
	sum_time=et-sum_st;
	sec2str(str,sum_time);
	printf("\n集計の対象となった延べ時間...%s\n",str);
	
	
	sec2str(str,DAY*((double)sum/(double)sum_time));
	printf("\n一日当たりの使用時間.......%s\n",str);
	sec2str(str,DAY*((double)sum*(double)num/(double)en/(double)sum_time));
	printf("一日当たりの実質使用時間...%s\n",str);
	
	return;
}



void	main(int argc,char **argv)
{
	FILE	*fp;
	
	switch(argc)
	{
		case 1:
		{
			usage();
			break;
		}
		case 2:
		{
			if ((fp=fopen(argv[1],"r"))==NULL)
			{
				puts("ファイルが見つかりません");
				exit(1);
			}
			strcpy(startKey,"START");
			strcpy(endKey,"END");
			break;
		}
		case 3:
		{
			usage();
			break;
		}
		case 4:
		{
			if ((fp=fopen(argv[1],"r"))==NULL)
			{
				puts("ファイルが見つかりません");
				exit(1);
			}
			strcpy(startKey,argv[2]);
			strcpy(endKey,argv[3]);
			break;
		}
	}
	summarize(fp);
}

