/*
 *
 * LogStat: Netcall-Statistik über TheAnswer.LOG
 *          FREEWARE
 *          Michael Balzer, 3. und 8. März 1992
 *          M.BALZER@AWORLD.ZER
 *
 * Auto: cc logstat.c -ff
 * Auto: ln logstat.o -lmf -lc
 *
 *  GNU: gcc logstat.c -o logstat $optimize
 *
 */

#include <exec/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void read_takt_info( void );
struct stat_header *find_server( char *name );
struct stat_monat *find_monat( struct stat_header *nh, int m, int j );
void parse( void );
void ausgabe( void );
long calctakt( struct stat_header *server,
	int tag, int monat, int jahr, int stunde );
int wochentag( int tag, int monat, int jahr );


FILE *fp;
#define BUFLEN 128
char buffer[BUFLEN];

struct stat_stunde
{
	int netcalls;
	int versuche;
};

struct stat_monat
{
	struct stat_monat *next_monat;
	int monat, jahr;
	int einheiten;
	long gesendet, empfangen;
};

struct stat_header
{
	struct stat_header *next_header;
	char server[32];
	struct stat_monat *first_monat;
	struct stat_stunde stunden[ 24 ];
	int takt1, takt2;		/* Normal, Billig */
	int start1, ende1;
} *first_server = NULL;


int main( int argc, char *argv[] )
{
	char *filename = "DFUe:Logs+Infos/TheAnswer.LOG";
	
	if( argc >= 2 )
	{
		if( *argv[1] == '?' )
		{
			printf( "SYNTAX: %s [dateiname]\n", argv[0] );
			printf( "Default-Datei: %s\n", filename );
			exit( 5 );
		}
		
		filename = argv[1];
	}
	
	read_takt_info();
	
	fp = fopen( filename, "r" );
	if( !fp )
	{
		printf( "Kann %s nicht öffnen.\n", filename );
		exit( 20 );
	}
	
	fgets( buffer, BUFLEN, fp );
	if( strncmp( buffer, "Log-File von THE ANSWER", 22 ) != 0 )
	{
		printf( "Kein TA-LogFile: %s\n", filename );
		exit( 20 );
	}

	parse();
	ausgabe();
	
	exit( 0 );
}


void read_takt_info( void )
{
	fp = fopen( "S:TaktInfo", "r" );
	
	if( fp )
	{
		struct stat_header *nh;
		char s[32];
		int t1, t2, st, en;
		
		do
		{
			fgets( s, 32, fp );
			fgets( buffer, BUFLEN, fp );
			sscanf( buffer, "%d %d %d %d", &t1, &t2, &st, &en );
			
			if( !feof(fp) )
			{
				/* Server finden / neu anlegen */
				s[ strlen(s) - 1 ] = 0;
				nh = find_server( s );
				
				nh->takt1  = t1;
				nh->takt2  = t2;
				nh->start1 = st;
				nh->ende1  = en;
			}
		}
		while( !feof(fp) );
		
		fclose( fp );
	}
}


struct stat_header *find_server( char *name )
{
	struct stat_header *nh;
	
	/* Server finden / neu anlegen */
	nh = first_server;
	if( !nh )
	{
		first_server = calloc( sizeof *nh, 1 );
		nh = first_server;
		strcpy( nh->server, name );
		nh->takt1  = 360;
		nh->takt2  = 720;
		nh->start1 = 8;
		nh->ende1  = 18;
	}
	else
	{
		while( strcmp(nh->server, name) )
		{
			if( ! nh->next_header )
			{
				nh->next_header = calloc( sizeof *nh, 1 );
				nh = nh->next_header;
				strcpy( nh->server, name );
				nh->takt1  = 360;
				nh->takt2  = 720;
				nh->start1 = 8;
				nh->ende1  = 18;
				
				break;
			}
			
			nh = nh->next_header;
		}
	}
	
	return( nh );
}


struct stat_monat *find_monat( struct stat_header *nh, int m, int j )
{
	struct stat_monat *nm;
	
	nm = nh->first_monat;
	if( !nm )
	{
		nh->first_monat = calloc( sizeof *nm, 1 );
		nm = nh->first_monat;
		nm->monat = m;
		nm->jahr = j;
	}
	else
	{
		while( nm->monat != m || nm->jahr != j )
		{
			if( ! nm->next_monat )
			{
				nm->next_monat = calloc( sizeof *nm, 1 );
				nm = nm->next_monat;
				nm->monat = m;
				nm->jahr = j;
				break;
			}
			
			nm = nm->next_monat;
		}
	}
	
	return( nm );
}


void parse( void )
{
	while( !feof(fp) )
	{
		char *s;
		
		/* Trennzeile suchen */
		do
		{
			if( ! fgets( buffer, BUFLEN, fp ) )
				return;
		}
		while( *buffer != '-' );
		
		fgets( buffer, BUFLEN, fp );
		
		if( strncmp( buffer, "Anwahl", 6 ) == 0 )
		{
			struct stat_header *nh;
			
			/* ':' ist fest auf Position 18 */
			s = buffer + 19;
			s[ strlen(s) - 1 ] = 0;
			
			/* Server finden / neu anlegen */
			nh = find_server( s );
			
			{
				/*
				 * Netcalls - Versuche - Uhrzeit
				 *
				 * Diese Statistik müßte eigentlich noch nach Wochentagen
				 * aufgeteilt werden...
				 */
	 			
				int zeit, vers;
				
				/* 1. Anwahlversuch */
				fgets( buffer, BUFLEN, fp );
				s = buffer + 30;
				
				zeit = (s[0]-'0') * 10 + (s[1]-'0');
				
				/* Ende des Netcalls */
				fgets( buffer, BUFLEN, fp );
				
				/* Anwahlversuche */
				fgets( buffer, BUFLEN, fp );
				s = buffer + 19;
				
				if( vers = atoi(s) )
				{
					nh->stunden[ zeit ].netcalls += 1;
					nh->stunden[ zeit ].versuche += vers;
				}
			}
			
			/* LF oder 'Keine Verbindung' */
			fgets( buffer, BUFLEN, fp );
			
			if( *buffer == '\n' )
			{
				int t, m, j;
				long zeit, takt;
				struct stat_monat *nm;
				
				/* Login um */
				fgets( buffer, BUFLEN, fp );
				s = buffer + 19;
				
				t = (s[0]-'0') *   10 + (s[1]-'0');
				m = (s[3]-'0') *   10 + (s[4]-'0');
				j = (s[6]-'0') * 1000 + (s[7]-'0') * 100
				  + (s[8]-'0') *   10 + (s[9]-'0');
				
				zeit = (s[11]-'0') * 10 + (s[12]-'0');
				takt = calctakt( nh, t, m, j, zeit );
				
				/* Monat suchen / neu anlegen */
				nm = find_monat( nh, m, j );
				
				/* Logout um */
				fgets( buffer, BUFLEN, fp );
				/* Zeit Online */
				fgets( buffer, BUFLEN, fp );
				
				s = buffer + 19;
				zeit = (s[0]-'0') * 36000 + (s[1]-'0') * 3600
					 + (s[3]-'0') *   600 + (s[4]-'0') *   60
					 + (s[6]-'0') *    10 + (s[7]-'0');
				nm->einheiten += zeit / takt + 1;
				
				/* 'NetCall abgebrochen' oder 'gesendete Bytes' */
				fgets( buffer, BUFLEN, fp );
				
				if( strncmp( buffer, "gesendet", 8 ) == 0 )
				{
					nm->gesendet += atol( buffer + 19 );
					
					/* empfangene Bytes */
					fgets( buffer, BUFLEN, fp );
					nm->empfangen += atol( buffer + 19 );
				}
			}
			/* if( *buffer == '\n' ) */
		}
		/* if( strncmp( buffer, "Anwahl", 6 ) == 0 ) */
	}
	/* while( !feof(fp) ) */
}


long calctakt( struct stat_header *server,
	int tag, int monat, int jahr, int stunde )
{
	long takt;
	int wt;
	
	wt = wochentag( tag, monat, jahr );
	
	if( wt==0 || wt==6 )
	{
		takt = server->takt2;
	}
	else
	{
		if( stunde >= server->start1 && stunde < server->ende1 )
			takt = server->takt1;
		else
			takt = server->takt2;
	}
	
	return takt;
}


int wochentag( int tag, int monat, int jahr )
{
	static int mtage[12] =
		{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
	
	int dj, wt;
	
	/* auf Anfang unseres Kalenders bezogen */
	dj = wt = jahr - 1601;
	
	/* plus Anzahl Schaltjahre */
	wt += (int)(dj / 4) - (int)(dj / 100) + (int)(dj / 400);
	
	/* ergibt Wochentagsverschiebung von */
	/* ( +1 weil 1.1.1601 ein Montag war (Bezugsdatum) ) */
	wt = (wt + 1) % 7;
	
	/* April-Länge bestimmen */
	if( !(jahr % 4) && (jahr % 100) || !(jahr % 400) )
		mtage[1] = 29;
	else
		mtage[1] = 28;
	
	/* Monate aufsummieren */
	while( --monat )
		wt += mtage[ monat-1 ];
	
	/* Tage dazu und mod 7 */
	wt = (wt + tag - 1) % 7;
	
	return( wt );
}


void ausgabe( void )
{
	struct stat_header *sh;
	
	printf( "LogStat TA2-Logbuch-Statistik von Michael Balzer\n" );
	/*
			"Anwahlversuche-Statistik: Je näher der Index an 1\n"
			"ist, desto weniger Anwahlversuche braucht man um die\n"
			"Zeit.\n" );
	 */
	
	sh = first_server;
	while( sh )
	{
		struct stat_monat *sm;
		int i;
		
		printf( "\nNetcall-Statistik für Server %s:\n\n"
				"Monat/Jahr | Gesendet   | Empfangen  | Gebühren \n"
				"-----------+------------+------------+----------\n",
				sh->server );
		
		sm = sh->first_monat;
		while( sm )
		{
			printf( "%02d / %04d  | %10ld | %10ld | %8.2f \n",
				sm->monat, sm->jahr, sm->gesendet, sm->empfangen,
				sm->einheiten * 0.23 );
			
			sm = sm->next_monat;
		}
		
		printf( "\nAnwahlversuche-Statistik für Server %s:\n\n"
				"Zeit  | Calls | Vers. | Index \n"
				"------+-------+-------+-------\n",
				sh->server );
		
		for( i=0; i<=23; i++ )
		{
			if( sh->stunden[i].netcalls )
				printf( "%02d:00 | %5d | %5d | %4.3f\n", i,
					sh->stunden[i].netcalls,
					sh->stunden[i].versuche,
					(float) sh->stunden[i].netcalls
					/ sh->stunden[i].versuche );
		}
		
		sh = sh->next_header;
	}
}
